added gtkaccelmap.sgml. other updates.
authorTim Janik <timj@gtk.org>
Tue, 13 Nov 2001 00:53:47 +0000 (00:53 +0000)
committerTim Janik <timj@src.gnome.org>
Tue, 13 Nov 2001 00:53:47 +0000 (00:53 +0000)
Mon Nov 12 23:06:38 2001  Tim Janik  <timj@gtk.org>

        * added gtkaccelmap.sgml. other updates.

Mon Nov 12 23:08:37 2001  Tim Janik  <timj@gtk.org>

* gtk/maketypes.awk: fix type utils generation on unix.

* gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
registry.

* gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
introduced ::accel_changed signal for change notification, and
gtk_accel_group_connect/disconnect to connect closures to accel groups.
made gtk_accel_group_attach/detach and gtk_accel_group_activate private
functions.
deprecated gtk_accel_group_ref/unref.

* gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
to accel group changed notification and basically operate on closures.
removed gtk_accel_label_get_accel_object and
gtk_accel_label_set_accel_object.
introduced gtk_accel_label_set_accel_closure, and for convenience,
gtk_accel_label_set_accel_widget.

* gtk/gtkitemfactory.[hc]: removed accelerator propagation code
which mostly moved into gtkaccelmap.[hc].
removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
and gtk_item_factory_print_func.

* gtk/gtkmain.c: call _gtk_accel_map_init().

* gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
that associates an accelerator path with menu items, through which
persistent accelerator settings on menu items are enabled.

* gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
paths of menu item can be default constructed to allow installation
of accelerators on menu items that don't come with an accelerator
binding by default.

* gtk/gtksettings.c: fix STRING type rc settings by special casing
them appropriately in the parser.

* gtk/gtksignal.[hc]: allow a class function offset of 0 for
gtk_signal_newv().

* gtk/gtkwidget.[hc]: accelerator API revamp.
removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
gtk_widget_(un)lock_accelerators.
accelerators maintained through gtk_widget_add/remove_accelerator()
are not runtime changable now, the correct sequence to setup a
widget for runtime changable accelerators is now:
  gtk_accel_map_add_entry(accel_path, key, mods);
  _gtk_widget_set_accel_path(widget, accel_path, accel_group);

* gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
group changes (as well as mnemonic changes) through the new signal
::accels_changed.

Sat Nov 10 12:08:56 2001  Tim Janik  <timj@gtk.org>

* gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
GString->string conversions.

56 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
demos/gtk-demo/appwindow.c
demos/gtk-demo/item_factory.c
demos/gtk-demo/menus.c
docs/reference/ChangeLog
docs/reference/gtk/gtk-docs.sgml
docs/reference/gtk/gtk-sections.txt
docs/reference/gtk/tmpl/gtk-unused.sgml
docs/reference/gtk/tmpl/gtkaccelgroup.sgml
docs/reference/gtk/tmpl/gtkaccellabel.sgml
docs/reference/gtk/tmpl/gtkcolorsel.sgml
docs/reference/gtk/tmpl/gtkcombo.sgml
docs/reference/gtk/tmpl/gtkdialog.sgml
docs/reference/gtk/tmpl/gtkenums.sgml
docs/reference/gtk/tmpl/gtkitemfactory.sgml
docs/reference/gtk/tmpl/gtkmenu.sgml
docs/reference/gtk/tmpl/gtkmenuitem.sgml
docs/reference/gtk/tmpl/gtkpaned.sgml
docs/reference/gtk/tmpl/gtktoolbar.sgml
docs/reference/gtk/tmpl/gtktreednd.sgml
docs/reference/gtk/tmpl/gtktreeview.sgml
docs/reference/gtk/tmpl/gtkwidget.sgml
docs/reference/gtk/tmpl/gtkwindow.sgml
gtk/Makefile.am
gtk/gtk.h
gtk/gtkaccelgroup.c
gtk/gtkaccelgroup.h
gtk/gtkaccellabel.c
gtk/gtkaccellabel.h
gtk/gtkaccelmap.c [new file with mode: 0644]
gtk/gtkaccelmap.h [new file with mode: 0644]
gtk/gtkitemfactory.c
gtk/gtkitemfactory.h
gtk/gtkmain.c
gtk/gtkmarshal.list
gtk/gtkmarshalers.list
gtk/gtkmenu.c
gtk/gtkmenu.h
gtk/gtkmenuitem.c
gtk/gtkmenuitem.h
gtk/gtknotebook.c
gtk/gtksettings.c
gtk/gtksignal.c
gtk/gtkwidget.c
gtk/gtkwidget.h
gtk/gtkwindow.c
gtk/gtkwindow.h
gtk/maketypes.awk
tests/testgtk.c
tests/testgtkrc

index 51ac8c00f93a7624ae5387ace6f2ce2bb57ed3f5..31c26db01ae74c8546bff2fca2e14cc60c46d1b3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/maketypes.awk: fix type utils generation on unix.
+
+       * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+       registry.
+
+       * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+       removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+       gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+       gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+       gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+       introduced ::accel_changed signal for change notification, and
+       gtk_accel_group_connect/disconnect to connect closures to accel groups.
+       made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+       functions.
+       deprecated gtk_accel_group_ref/unref.
+
+       * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+       to accel group changed notification and basically operate on closures.
+       removed gtk_accel_label_get_accel_object and
+       gtk_accel_label_set_accel_object.
+       introduced gtk_accel_label_set_accel_closure, and for convenience,
+       gtk_accel_label_set_accel_widget.
+
+       * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+       which mostly moved into gtkaccelmap.[hc].
+       removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+       and gtk_item_factory_print_func.
+
+       * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+       * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+       that associates an accelerator path with menu items, through which
+       persistent accelerator settings on menu items are enabled.
+
+       * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+       paths of menu item can be default constructed to allow installation
+       of accelerators on menu items that don't come with an accelerator
+       binding by default.
+
+       * gtk/gtksettings.c: fix STRING type rc settings by special casing
+       them appropriately in the parser.
+
+       * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+       gtk_signal_newv().
+
+       * gtk/gtkwidget.[hc]: accelerator API revamp.
+       removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+       gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+       gtk_widget_(un)lock_accelerators.
+       accelerators maintained through gtk_widget_add/remove_accelerator()
+       are not runtime changable now, the correct sequence to setup a
+       widget for runtime changable accelerators is now:
+         gtk_accel_map_add_entry(accel_path, key, mods);
+         _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+       * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+       group changes (as well as mnemonic changes) through the new signal
+       ::accels_changed.
+
+Sat Nov 10 12:08:56 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+       GString->string conversions.
+
 Mon Nov 12 19:33:52 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
index 51ac8c00f93a7624ae5387ace6f2ce2bb57ed3f5..31c26db01ae74c8546bff2fca2e14cc60c46d1b3 100644 (file)
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/maketypes.awk: fix type utils generation on unix.
+
+       * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+       registry.
+
+       * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+       removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+       gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+       gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+       gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+       introduced ::accel_changed signal for change notification, and
+       gtk_accel_group_connect/disconnect to connect closures to accel groups.
+       made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+       functions.
+       deprecated gtk_accel_group_ref/unref.
+
+       * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+       to accel group changed notification and basically operate on closures.
+       removed gtk_accel_label_get_accel_object and
+       gtk_accel_label_set_accel_object.
+       introduced gtk_accel_label_set_accel_closure, and for convenience,
+       gtk_accel_label_set_accel_widget.
+
+       * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+       which mostly moved into gtkaccelmap.[hc].
+       removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+       and gtk_item_factory_print_func.
+
+       * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+       * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+       that associates an accelerator path with menu items, through which
+       persistent accelerator settings on menu items are enabled.
+
+       * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+       paths of menu item can be default constructed to allow installation
+       of accelerators on menu items that don't come with an accelerator
+       binding by default.
+
+       * gtk/gtksettings.c: fix STRING type rc settings by special casing
+       them appropriately in the parser.
+
+       * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+       gtk_signal_newv().
+
+       * gtk/gtkwidget.[hc]: accelerator API revamp.
+       removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+       gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+       gtk_widget_(un)lock_accelerators.
+       accelerators maintained through gtk_widget_add/remove_accelerator()
+       are not runtime changable now, the correct sequence to setup a
+       widget for runtime changable accelerators is now:
+         gtk_accel_map_add_entry(accel_path, key, mods);
+         _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+       * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+       group changes (as well as mnemonic changes) through the new signal
+       ::accels_changed.
+
+Sat Nov 10 12:08:56 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+       GString->string conversions.
+
 Mon Nov 12 19:33:52 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
index 51ac8c00f93a7624ae5387ace6f2ce2bb57ed3f5..31c26db01ae74c8546bff2fca2e14cc60c46d1b3 100644 (file)
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/maketypes.awk: fix type utils generation on unix.
+
+       * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+       registry.
+
+       * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+       removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+       gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+       gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+       gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+       introduced ::accel_changed signal for change notification, and
+       gtk_accel_group_connect/disconnect to connect closures to accel groups.
+       made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+       functions.
+       deprecated gtk_accel_group_ref/unref.
+
+       * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+       to accel group changed notification and basically operate on closures.
+       removed gtk_accel_label_get_accel_object and
+       gtk_accel_label_set_accel_object.
+       introduced gtk_accel_label_set_accel_closure, and for convenience,
+       gtk_accel_label_set_accel_widget.
+
+       * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+       which mostly moved into gtkaccelmap.[hc].
+       removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+       and gtk_item_factory_print_func.
+
+       * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+       * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+       that associates an accelerator path with menu items, through which
+       persistent accelerator settings on menu items are enabled.
+
+       * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+       paths of menu item can be default constructed to allow installation
+       of accelerators on menu items that don't come with an accelerator
+       binding by default.
+
+       * gtk/gtksettings.c: fix STRING type rc settings by special casing
+       them appropriately in the parser.
+
+       * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+       gtk_signal_newv().
+
+       * gtk/gtkwidget.[hc]: accelerator API revamp.
+       removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+       gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+       gtk_widget_(un)lock_accelerators.
+       accelerators maintained through gtk_widget_add/remove_accelerator()
+       are not runtime changable now, the correct sequence to setup a
+       widget for runtime changable accelerators is now:
+         gtk_accel_map_add_entry(accel_path, key, mods);
+         _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+       * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+       group changes (as well as mnemonic changes) through the new signal
+       ::accels_changed.
+
+Sat Nov 10 12:08:56 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+       GString->string conversions.
+
 Mon Nov 12 19:33:52 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
index 51ac8c00f93a7624ae5387ace6f2ce2bb57ed3f5..31c26db01ae74c8546bff2fca2e14cc60c46d1b3 100644 (file)
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/maketypes.awk: fix type utils generation on unix.
+
+       * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+       registry.
+
+       * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+       removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+       gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+       gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+       gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+       introduced ::accel_changed signal for change notification, and
+       gtk_accel_group_connect/disconnect to connect closures to accel groups.
+       made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+       functions.
+       deprecated gtk_accel_group_ref/unref.
+
+       * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+       to accel group changed notification and basically operate on closures.
+       removed gtk_accel_label_get_accel_object and
+       gtk_accel_label_set_accel_object.
+       introduced gtk_accel_label_set_accel_closure, and for convenience,
+       gtk_accel_label_set_accel_widget.
+
+       * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+       which mostly moved into gtkaccelmap.[hc].
+       removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+       and gtk_item_factory_print_func.
+
+       * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+       * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+       that associates an accelerator path with menu items, through which
+       persistent accelerator settings on menu items are enabled.
+
+       * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+       paths of menu item can be default constructed to allow installation
+       of accelerators on menu items that don't come with an accelerator
+       binding by default.
+
+       * gtk/gtksettings.c: fix STRING type rc settings by special casing
+       them appropriately in the parser.
+
+       * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+       gtk_signal_newv().
+
+       * gtk/gtkwidget.[hc]: accelerator API revamp.
+       removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+       gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+       gtk_widget_(un)lock_accelerators.
+       accelerators maintained through gtk_widget_add/remove_accelerator()
+       are not runtime changable now, the correct sequence to setup a
+       widget for runtime changable accelerators is now:
+         gtk_accel_map_add_entry(accel_path, key, mods);
+         _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+       * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+       group changes (as well as mnemonic changes) through the new signal
+       ::accels_changed.
+
+Sat Nov 10 12:08:56 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+       GString->string conversions.
+
 Mon Nov 12 19:33:52 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
index 51ac8c00f93a7624ae5387ace6f2ce2bb57ed3f5..31c26db01ae74c8546bff2fca2e14cc60c46d1b3 100644 (file)
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/maketypes.awk: fix type utils generation on unix.
+
+       * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+       registry.
+
+       * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+       removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+       gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+       gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+       gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+       introduced ::accel_changed signal for change notification, and
+       gtk_accel_group_connect/disconnect to connect closures to accel groups.
+       made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+       functions.
+       deprecated gtk_accel_group_ref/unref.
+
+       * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+       to accel group changed notification and basically operate on closures.
+       removed gtk_accel_label_get_accel_object and
+       gtk_accel_label_set_accel_object.
+       introduced gtk_accel_label_set_accel_closure, and for convenience,
+       gtk_accel_label_set_accel_widget.
+
+       * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+       which mostly moved into gtkaccelmap.[hc].
+       removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+       and gtk_item_factory_print_func.
+
+       * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+       * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+       that associates an accelerator path with menu items, through which
+       persistent accelerator settings on menu items are enabled.
+
+       * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+       paths of menu item can be default constructed to allow installation
+       of accelerators on menu items that don't come with an accelerator
+       binding by default.
+
+       * gtk/gtksettings.c: fix STRING type rc settings by special casing
+       them appropriately in the parser.
+
+       * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+       gtk_signal_newv().
+
+       * gtk/gtkwidget.[hc]: accelerator API revamp.
+       removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+       gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+       gtk_widget_(un)lock_accelerators.
+       accelerators maintained through gtk_widget_add/remove_accelerator()
+       are not runtime changable now, the correct sequence to setup a
+       widget for runtime changable accelerators is now:
+         gtk_accel_map_add_entry(accel_path, key, mods);
+         _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+       * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+       group changes (as well as mnemonic changes) through the new signal
+       ::accels_changed.
+
+Sat Nov 10 12:08:56 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+       GString->string conversions.
+
 Mon Nov 12 19:33:52 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
index 51ac8c00f93a7624ae5387ace6f2ce2bb57ed3f5..31c26db01ae74c8546bff2fca2e14cc60c46d1b3 100644 (file)
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/maketypes.awk: fix type utils generation on unix.
+
+       * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+       registry.
+
+       * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+       removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+       gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+       gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+       gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+       introduced ::accel_changed signal for change notification, and
+       gtk_accel_group_connect/disconnect to connect closures to accel groups.
+       made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+       functions.
+       deprecated gtk_accel_group_ref/unref.
+
+       * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+       to accel group changed notification and basically operate on closures.
+       removed gtk_accel_label_get_accel_object and
+       gtk_accel_label_set_accel_object.
+       introduced gtk_accel_label_set_accel_closure, and for convenience,
+       gtk_accel_label_set_accel_widget.
+
+       * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+       which mostly moved into gtkaccelmap.[hc].
+       removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+       and gtk_item_factory_print_func.
+
+       * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+       * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+       that associates an accelerator path with menu items, through which
+       persistent accelerator settings on menu items are enabled.
+
+       * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+       paths of menu item can be default constructed to allow installation
+       of accelerators on menu items that don't come with an accelerator
+       binding by default.
+
+       * gtk/gtksettings.c: fix STRING type rc settings by special casing
+       them appropriately in the parser.
+
+       * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+       gtk_signal_newv().
+
+       * gtk/gtkwidget.[hc]: accelerator API revamp.
+       removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+       gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+       gtk_widget_(un)lock_accelerators.
+       accelerators maintained through gtk_widget_add/remove_accelerator()
+       are not runtime changable now, the correct sequence to setup a
+       widget for runtime changable accelerators is now:
+         gtk_accel_map_add_entry(accel_path, key, mods);
+         _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+       * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+       group changes (as well as mnemonic changes) through the new signal
+       ::accels_changed.
+
+Sat Nov 10 12:08:56 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+       GString->string conversions.
+
 Mon Nov 12 19:33:52 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
index 51ac8c00f93a7624ae5387ace6f2ce2bb57ed3f5..31c26db01ae74c8546bff2fca2e14cc60c46d1b3 100644 (file)
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/maketypes.awk: fix type utils generation on unix.
+
+       * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+       registry.
+
+       * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+       removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+       gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+       gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+       gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+       introduced ::accel_changed signal for change notification, and
+       gtk_accel_group_connect/disconnect to connect closures to accel groups.
+       made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+       functions.
+       deprecated gtk_accel_group_ref/unref.
+
+       * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+       to accel group changed notification and basically operate on closures.
+       removed gtk_accel_label_get_accel_object and
+       gtk_accel_label_set_accel_object.
+       introduced gtk_accel_label_set_accel_closure, and for convenience,
+       gtk_accel_label_set_accel_widget.
+
+       * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+       which mostly moved into gtkaccelmap.[hc].
+       removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+       and gtk_item_factory_print_func.
+
+       * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+       * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+       that associates an accelerator path with menu items, through which
+       persistent accelerator settings on menu items are enabled.
+
+       * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+       paths of menu item can be default constructed to allow installation
+       of accelerators on menu items that don't come with an accelerator
+       binding by default.
+
+       * gtk/gtksettings.c: fix STRING type rc settings by special casing
+       them appropriately in the parser.
+
+       * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+       gtk_signal_newv().
+
+       * gtk/gtkwidget.[hc]: accelerator API revamp.
+       removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+       gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+       gtk_widget_(un)lock_accelerators.
+       accelerators maintained through gtk_widget_add/remove_accelerator()
+       are not runtime changable now, the correct sequence to setup a
+       widget for runtime changable accelerators is now:
+         gtk_accel_map_add_entry(accel_path, key, mods);
+         _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+       * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+       group changes (as well as mnemonic changes) through the new signal
+       ::accels_changed.
+
+Sat Nov 10 12:08:56 2001  Tim Janik  <timj@gtk.org>
+
+       * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+       GString->string conversions.
+
 Mon Nov 12 19:33:52 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
index c052bcbc608ae9d8180b42dfbb1725ecb8a0b551..5020152ff53ccb6d6a34f2c6e5d959f83027c55f 100644 (file)
@@ -213,8 +213,8 @@ do_appwindow (void)
        */
       
       accel_group = gtk_accel_group_new ();
-      gtk_accel_group_attach (accel_group, G_OBJECT (window));
-      gtk_accel_group_unref (accel_group);
+      gtk_window_add_accel_group (window, accel_group);
+      g_object_unref (accel_group);
       
       item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
 
index 34f3cb51d6930d97c5ea6008d2f67c7e99d8e809..390f4a75c3e7f1bbb9a20f79268069aec51c2ee7 100644 (file)
@@ -68,7 +68,7 @@ do_item_factory (void)
       item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
       g_object_set_data_full (G_OBJECT (window), "<main>",
                              item_factory, (GDestroyNotify) g_object_unref);
-      gtk_accel_group_attach (accel_group, G_OBJECT (window));
+      gtk_window_add_accel_group (window, accel_group);
       gtk_window_set_title (GTK_WINDOW (window), "Item Factory");
       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
       gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
index 99899a7d322180735df4a59d6e3454623bfffd11..60e20e1355c67dc5e5211a7550affca0371eb224 100644 (file)
@@ -98,7 +98,7 @@ do_menus (void)
                        G_CALLBACK (gtk_true), NULL);
       
       accel_group = gtk_accel_group_new ();
-      gtk_accel_group_attach (accel_group, G_OBJECT (window));
+      gtk_window_add_accel_group (window, accel_group);
 
       gtk_window_set_title (GTK_WINDOW (window), "menus");
       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
@@ -150,7 +150,7 @@ do_menus (void)
                                  accel_group,
                                  GDK_F1,
                                  0,
-                                 GTK_ACCEL_VISIBLE | GTK_ACCEL_SIGNAL_VISIBLE);
+                                 GTK_ACCEL_VISIBLE);
       menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
       gtk_widget_show (menuitem);
@@ -175,7 +175,6 @@ do_menus (void)
                                  GDK_F3,
                                  0,
                                  GTK_ACCEL_VISIBLE);
-      gtk_widget_lock_accelerators (menuitem);
       
       optionmenu = gtk_option_menu_new ();
       gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
index 963916c9c63e99ef0b11f256f40b0a7957bc2afa..6a8b1c51387e39f90e3824ee626b91b35c227405 100644 (file)
@@ -1,3 +1,7 @@
+Mon Nov 12 23:06:38 2001  Tim Janik  <timj@gtk.org>
+
+       * added gtkaccelmap.sgml. other updates.
+
 2001-11-11  Matthias Clasen  <matthiasc@poet.de>
 
        * gdk-pixbuf/gdk-pixbuf-rendering.sgml, 
index fd0c2acdb8c3c0aa289fd3e01c05e066610d3789..50ee7a9bee5f9d16d6d7eab5614a59d19b727f8a 100644 (file)
 <!entity gtk-Styles SYSTEM "sgml/gtkstyle.sgml">
 <!entity gtk-Themes SYSTEM "sgml/gtkthemes.sgml">
 <!entity gtk-Resource-Files SYSTEM "sgml/gtkrc.sgml">
-<!entity gtk-Keyboard-Accelerators SYSTEM "sgml/gtkaccelgroup.sgml">
+<!entity GtkAccelGroup SYSTEM "sgml/gtkaccelgroup.sgml">
+<!entity gtk-accel-map SYSTEM "sgml/gtkaccelmap.sgml">
 <!entity gtk-Selections SYSTEM "sgml/gtkselection.sgml">
 <!entity gtk-Clipboards SYSTEM "sgml/gtkclipboard.sgml">
 <!entity gtk-Drag-and-Drop SYSTEM "sgml/gtkdnd.sgml">
@@ -248,7 +249,8 @@ that is, GUI components such as #GtkButton or #GtkTextView.
     <title>GTK+ Core Reference</title>
 
     &gtk-General;
-    &gtk-Keyboard-Accelerators;
+    &GtkAccelGroup;
+    &gtk-accel-map;
     &gtk-Clipboards;
     &gtk-Drag-and-Drop;
     &gtk-Stock-Items;
index 37dbea2ecb7787c5017c11f86b38e01df5339b63..e184fd744f5f2e64e7dd5c4de399a1aa8e225f35 100644 (file)
@@ -1,6 +1,52 @@
 
 <INCLUDE>gtk/gtk.h</INCLUDE>
 
+<SECTION>
+<FILE>gtkaccelgroup</FILE>
+<TITLE>Keyboard Accelerators</TITLE>
+GtkAccelGroup
+gtk_accel_group_get_type
+gtk_accel_group_new
+gtk_accel_group_connect
+gtk_accel_group_disconnect
+gtk_accel_group_query
+gtk_accel_group_activate
+gtk_accel_groups_activate
+gtk_accel_group_lock
+gtk_accel_group_unlock
+gtk_accelerator_valid
+gtk_accelerator_parse
+gtk_accelerator_name
+gtk_accelerator_set_default_mod_mask
+gtk_accelerator_get_default_mod_mask
+<SUBSECTION Private>
+<SUBSECTION Standard>
+GtkAccelGroupClass
+GTK_TYPE_ACCEL_GROUP
+GTK_ACCEL_GROUP
+GTK_IS_ACCEL_GROUP
+GTK_ACCEL_GROUP_CLASS
+GTK_IS_ACCEL_GROUP_CLASS
+GTK_ACCEL_GROUP_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gtkaccelmap</FILE>
+<TITLE>Accelerator Maps</TITLE>
+GtkAccelMapNotify
+GtkAccelMapForeach
+gtk_accel_map_add_entry
+gtk_accel_map_lookup_entry
+gtk_accel_map_change_entry
+gtk_accel_map_add_notifer
+gtk_accel_map_remove_notifer
+gtk_accel_map_load
+gtk_accel_map_save
+gtk_accel_map_foreach
+gtk_accel_map_load_fd
+gtk_accel_map_save_fd
+</SECTION>
+
 <SECTION>
 <FILE>gtkaccellabel</FILE>
 <TITLE>GtkAccelLabel</TITLE>
@@ -1428,6 +1474,7 @@ gtk_menu_reorder_child
 gtk_menu_popup
 gtk_menu_set_accel_group
 gtk_menu_get_accel_group
+gtk_menu_set_accel_path
 gtk_menu_set_title
 gtk_menu_get_tearoff_state
 gtk_menu_get_title
@@ -1481,6 +1528,7 @@ gtk_menu_item_new_with_label
 gtk_menu_item_new_with_mnemonic
 gtk_menu_item_set_right_justified
 gtk_menu_item_set_submenu
+gtk_menu_item_set_accel_path  
 gtk_menu_item_remove_submenu
 gtk_menu_item_select
 gtk_menu_item_deselect
@@ -3880,49 +3928,6 @@ gtk_rc_style_get_type
 GtkRcContext
 </SECTION>
 
-<SECTION>
-<FILE>gtkaccelgroup</FILE>
-<TITLE>Keyboard Accelerators</TITLE>
-GtkAccelGroup
-gtk_accel_group_new
-gtk_accel_group_get_default
-gtk_accel_group_ref
-gtk_accel_group_unref
-gtk_accel_group_activate
-gtk_accel_groups_activate
-gtk_accel_group_attach
-gtk_accel_group_detach
-gtk_accel_group_add
-gtk_accel_group_remove
-gtk_accel_group_lock
-gtk_accel_group_unlock
-gtk_accelerator_valid
-gtk_accelerator_parse
-gtk_accelerator_name
-gtk_accelerator_set_default_mod_mask
-gtk_accelerator_get_default_mod_mask
-<SUBSECTION Private>
-GtkAccelEntry
-gtk_accel_group_get_type
-gtk_accel_group_get_entry
-gtk_accel_group_lock_entry
-gtk_accel_group_unlock_entry
-gtk_accel_group_handle_add
-gtk_accel_group_handle_remove
-gtk_accel_group_create_add
-gtk_accel_group_create_remove
-gtk_accel_groups_from_object
-gtk_accel_group_entries_from_object
-<SUBSECTION Standard>
-GtkAccelGroupClass
-GTK_ACCEL_GROUP
-GTK_TYPE_ACCEL_GROUP
-GTK_ACCEL_GROUP_CLASS
-GTK_ACCEL_GROUP_GET_CLASS
-GTK_IS_ACCEL_GROUP
-GTK_IS_ACCEL_GROUP_CLASS
-</SECTION>
-
 <SECTION>
 <FILE>gtkselection</FILE>
 <TITLE>Selections</TITLE>
index 91412b12e88589acd43c5da5de479cf581c241b5..86e08b9c736d2731130d05b514858504c0a01902 100644 (file)
@@ -495,9 +495,9 @@ This is a private struct used by GTK+ internally, don't worry about it.
 @object: 
 @signal_id: 
 
-<!-- ##### ARG GtkAccelLabel:accel-widget ##### -->
+<!-- ##### ARG GtkAccelLabel:accel-object ##### -->
 <para>
-The widget whose accelerators are to be shown by the #GtkAccelLabel.
+
 </para>
 
 
@@ -1186,6 +1186,29 @@ produce superscript and subscript.
 @parent: 
 @priv: 
 
+<!-- ##### USER_FUNCTION GtkTreeViewDraggableFunc ##### -->
+<para>
+
+</para>
+
+@tree_view: 
+@context: 
+@path: 
+@user_data: 
+@Returns: 
+
+<!-- ##### USER_FUNCTION GtkTreeViewDroppableFunc ##### -->
+<para>
+
+</para>
+
+@tree_view: 
+@context: 
+@path: 
+@pos: 
+@user_data: 
+@Returns: 
+
 <!-- ##### ARG GtkVScale:adjustment ##### -->
 <para>
 the #GtkAdjustment which sets the range of the scale.
@@ -1207,6 +1230,18 @@ the #GtkAdjustment which sets the range of the scale.
 @arg1: 
 @Returns: 
 
+<!-- ##### SIGNAL GtkWidget::add-accelerator ##### -->
+<para>
+
+</para>
+
+@widget: the object which received the signal.
+@accel_signal_id: 
+@accel_group: 
+@accel_key: 
+@accel_mods: 
+@accel_flags: 
+
 <!-- ##### SIGNAL GtkWidget::debug-msg ##### -->
 <para>
 
@@ -1237,6 +1272,16 @@ the #GtkAdjustment which sets the range of the scale.
 
 @widget: the object which received the signal.
 
+<!-- ##### SIGNAL GtkWidget::remove-accelerator ##### -->
+<para>
+
+</para>
+
+@widget: the object which received the signal.
+@accel_group: 
+@accel_key: 
+@accel_mods: 
+
 <!-- ##### ARG GtkWidget:height ##### -->
 <para>
 
@@ -1273,6 +1318,37 @@ If the window shrinks automatically when widgets within it shrink.
 </para>
 
 
+<!-- ##### FUNCTION gtk_accel_group_activate ##### -->
+<para>
+
+</para>
+
+@accel_group: 
+@accel_key: 
+@accel_mods: 
+@Returns: 
+
+<!-- ##### FUNCTION gtk_accel_group_add ##### -->
+<para>
+
+</para>
+
+@accel_group: 
+@path: 
+@accel_key: 
+@accel_mods: 
+@accel_flags: 
+@object: 
+@accel_signal: 
+
+<!-- ##### FUNCTION gtk_accel_group_attach ##### -->
+<para>
+
+</para>
+
+@accel_group: 
+@object: 
+
 <!-- ##### FUNCTION gtk_accel_group_create_add ##### -->
 <para>
 
@@ -1293,6 +1369,14 @@ If the window shrinks automatically when widgets within it shrink.
 @handler_offset: 
 @Returns: 
 
+<!-- ##### FUNCTION gtk_accel_group_detach ##### -->
+<para>
+
+</para>
+
+@accel_group: 
+@object: 
+
 <!-- ##### FUNCTION gtk_accel_group_entries_from_object ##### -->
 <para>
 
@@ -1301,6 +1385,13 @@ If the window shrinks automatically when widgets within it shrink.
 @object: 
 @Returns: 
 
+<!-- ##### FUNCTION gtk_accel_group_get_default ##### -->
+<para>
+
+</para>
+
+@Returns: 
+
 <!-- ##### FUNCTION gtk_accel_group_get_entry ##### -->
 <para>
 
@@ -1342,6 +1433,24 @@ If the window shrinks automatically when widgets within it shrink.
 @accel_key: 
 @accel_mods: 
 
+<!-- ##### MACRO gtk_accel_group_ref ##### -->
+<para>
+
+</para>
+
+@Returns: 
+@accel_group: 
+
+<!-- ##### FUNCTION gtk_accel_group_remove ##### -->
+<para>
+
+</para>
+
+@accel_group: 
+@accel_key: 
+@accel_mods: 
+@object: 
+
 <!-- ##### FUNCTION gtk_accel_group_unlock_entry ##### -->
 <para>
 
@@ -1351,6 +1460,13 @@ If the window shrinks automatically when widgets within it shrink.
 @accel_key: 
 @accel_mods: 
 
+<!-- ##### MACRO gtk_accel_group_unref ##### -->
+<para>
+
+</para>
+
+@accel_group: 
+
 <!-- ##### FUNCTION gtk_accel_groups_from_object ##### -->
 <para>
 
@@ -1359,6 +1475,22 @@ If the window shrinks automatically when widgets within it shrink.
 @object: 
 @Returns: 
 
+<!-- ##### FUNCTION gtk_accel_label_get_accel_object ##### -->
+<para>
+
+</para>
+
+@accel_label: 
+@Returns: 
+
+<!-- ##### FUNCTION gtk_accel_label_set_accel_object ##### -->
+<para>
+
+</para>
+
+@accel_label: 
+@accel_object: 
+
 <!-- ##### FUNCTION gtk_arg_copy ##### -->
 <para>
 It will either copy data into an existing argument or allocate a new argument
@@ -1905,6 +2037,54 @@ Get the type of GtkIdentifier.
 
 @Returns: 
 
+<!-- ##### FUNCTION gtk_item_factory_dump_items ##### -->
+<para>
+
+</para>
+
+@path_pspec: 
+@modified_only: 
+@print_func: 
+@func_data: 
+
+<!-- ##### FUNCTION gtk_item_factory_dump_rc ##### -->
+<para>
+
+</para>
+
+@file_name: 
+@path_pspec: 
+@modified_only: 
+
+<!-- ##### FUNCTION gtk_item_factory_parse_rc ##### -->
+<para>
+
+</para>
+
+@file_name: 
+
+<!-- ##### FUNCTION gtk_item_factory_parse_rc_scanner ##### -->
+<para>
+
+</para>
+
+@scanner: 
+
+<!-- ##### FUNCTION gtk_item_factory_parse_rc_string ##### -->
+<para>
+
+</para>
+
+@rc_string: 
+
+<!-- ##### FUNCTION gtk_item_factory_print_func ##### -->
+<para>
+
+</para>
+
+@FILE_pointer: 
+@string: 
+
 <!-- ##### FUNCTION gtk_label_set_markup_with_accel ##### -->
 <para>
 
@@ -2715,6 +2895,31 @@ a gtk_object_unref().
 @width: 
 @size: 
 
+<!-- ##### FUNCTION gtk_tree_view_set_rows_drag_dest ##### -->
+<para>
+
+</para>
+
+@tree_view: 
+@targets: 
+@n_targets: 
+@actions: 
+@location_droppable_func: 
+@user_data: 
+
+<!-- ##### FUNCTION gtk_tree_view_set_rows_drag_source ##### -->
+<para>
+
+</para>
+
+@tree_view: 
+@start_button_mask: 
+@targets: 
+@n_targets: 
+@actions: 
+@row_draggable_func: 
+@user_data: 
+
 <!-- ##### FUNCTION gtk_type_check_class_cast ##### -->
 <para>
 Given a GtkTypeClass pointer @klass, and a GtkType @cast_type, make
@@ -2829,6 +3034,25 @@ Set the varargs type for a fundamental type @foreign_type.
 fundamental type.
 @varargs_type: Must be a GtkType which is either structured or flag, or NONE.
 
+<!-- ##### FUNCTION gtk_widget_accelerator_signal ##### -->
+<para>
+
+</para>
+
+@widget: 
+@accel_group: 
+@accel_key: 
+@accel_mods: 
+@Returns: 
+
+<!-- ##### FUNCTION gtk_widget_accelerators_locked ##### -->
+<para>
+
+</para>
+
+@widget: 
+@Returns: 
+
 <!-- ##### FUNCTION gtk_widget_activate_mnemonic ##### -->
 <para>
 
@@ -2847,6 +3071,13 @@ fundamental type.
 @width: 
 @height: 
 
+<!-- ##### FUNCTION gtk_widget_lock_accelerators ##### -->
+<para>
+
+</para>
+
+@widget: 
+
 <!-- ##### FUNCTION gtk_widget_pop_style ##### -->
 <para>
 
@@ -2869,6 +3100,15 @@ fundamental type.
 
 @style: 
 
+<!-- ##### FUNCTION gtk_widget_remove_accelerators ##### -->
+<para>
+
+</para>
+
+@widget: 
+@accel_signal: 
+@visible_only: 
+
 <!-- ##### FUNCTION gtk_widget_set_default_style ##### -->
 <para>
 
@@ -2876,6 +3116,13 @@ fundamental type.
 
 @style: 
 
+<!-- ##### FUNCTION gtk_widget_unlock_accelerators ##### -->
+<para>
+
+</para>
+
+@widget: 
+
 <!-- ##### FUNCTION gtk_window_activate_mnemonic ##### -->
 <para>
 
index a0fc59a5290828f489eac54a0702269af9814685..b069f7e7385605cc41ddeabbabfea3d353f74ead 100644 (file)
@@ -1,9 +1,9 @@
 <!-- ##### SECTION Title ##### -->
-Keyboard Accelerators
+Keyboard Accelerator Groups
 
 <!-- ##### SECTION Short_Description ##### -->
 
-global keyboard accelerators (for an entire #GtkWindow)
+Groups of global keyboard accelerators for an entire #GtkWindow
 
 <!-- ##### SECTION Long_Description ##### -->
 <para>
@@ -11,14 +11,15 @@ A #GtkAccelGroup represents a group of keyboard accelerators,
 typically attached to a toplevel #GtkWindow (with
 gtk_window_add_accel_group()). Usually you won't need to create a
 #GtkAccelGroup directly; instead, when using #GtkItemFactory, GTK+
-automatically sets up the accelerators for your menus.
+automatically sets up the accelerators for your menus in the item
+factory's #GtkAccelGroup.
 </para>
 
 <para>
 Note that <firstterm>accelerators</firstterm> are different from
 <firstterm>mnemonics</firstterm>. Accelerators are shortcuts for
 activating a menu item; they appear alongside the menu item they're a
-shortcut for, for example "Ctrl+Q" might appear alongside the "Quit"
+shortcut for. For example "Ctrl+Q" might appear alongside the "Quit"
 menu item. Mnemonics are shortcuts for GUI elements such as text
 entries or buttons; they appear as underlined characters. See
 gtk_label_new_with_mnemonic(). Menu items can have both accelerators
@@ -27,16 +28,17 @@ and mnemonics, of course.
 
 <!-- ##### SECTION See_Also ##### -->
 <para>
-gtk_label_new_with_mnemonic(), gtk_window_add_accel_group()
+gtk_window_add_accel_group(), gtk_accel_map_change_entry(),
+gtk_item_factory_new(), gtk_label_new_with_mnemonic()
 </para>
 
 <!-- ##### STRUCT GtkAccelGroup ##### -->
 <para>
-On opaque data type representing a group of accelerators.
+An object representing and maintaining a group of accelerators.
 </para>
 
 
-<!-- ##### FUNCTION gtk_accel_group_new ##### -->
+<!-- ##### FUNCTION gtk_accel_group_get_type ##### -->
 <para>
 
 </para>
@@ -44,32 +46,15 @@ On opaque data type representing a group of accelerators.
 @Returns: 
 
 
-<!-- ##### FUNCTION gtk_accel_group_get_default ##### -->
-<para>
-
-</para>
-
-@Returns: 
-
-
-<!-- ##### FUNCTION gtk_accel_group_ref ##### -->
+<!-- ##### FUNCTION gtk_accel_group_new ##### -->
 <para>
 
 </para>
 
-@accel_group: 
 @Returns: 
 
 
-<!-- ##### FUNCTION gtk_accel_group_unref ##### -->
-<para>
-
-</para>
-
-@accel_group: 
-
-
-<!-- ##### FUNCTION gtk_accel_group_activate ##### -->
+<!-- ##### FUNCTION gtk_accel_group_connect ##### -->
 <para>
 
 </para>
@@ -77,39 +62,25 @@ On opaque data type representing a group of accelerators.
 @accel_group: 
 @accel_key: 
 @accel_mods: 
-@Returns: 
+@accel_flags: 
+@closure: 
+@accel_path_quark: 
+<!-- # Unused Parameters # -->
+@path_quark: 
 
 
-<!-- ##### FUNCTION gtk_accel_groups_activate ##### -->
+<!-- ##### FUNCTION gtk_accel_group_disconnect ##### -->
 <para>
 
 </para>
 
-@object
+@accel_group
 @accel_key: 
 @accel_mods: 
 @Returns: 
 
 
-<!-- ##### FUNCTION gtk_accel_group_attach ##### -->
-<para>
-
-</para>
-
-@accel_group: 
-@object: 
-
-
-<!-- ##### FUNCTION gtk_accel_group_detach ##### -->
-<para>
-
-</para>
-
-@accel_group: 
-@object: 
-
-
-<!-- ##### FUNCTION gtk_accel_group_add ##### -->
+<!-- ##### FUNCTION gtk_accel_group_query ##### -->
 <para>
 
 </para>
@@ -117,19 +88,20 @@ On opaque data type representing a group of accelerators.
 @accel_group: 
 @accel_key: 
 @accel_mods: 
-@accel_flags: 
-@object: 
-@accel_signal: 
+@n_entries: 
+@Returns: 
 
 
-<!-- ##### FUNCTION gtk_accel_group_remove ##### -->
+<!-- ##### FUNCTION gtk_accel_groups_activate ##### -->
 <para>
 
 </para>
 
-@accel_group
+@acceleratable
 @accel_key: 
 @accel_mods: 
+@Returns: 
+<!-- # Unused Parameters # -->
 @object: 
 
 
index a434252bbd1d0147857df017d88e61d6d2bfdbc2..4587cf7515a57b2621dcda82c438de2b13e57f53 100644 (file)
@@ -94,7 +94,7 @@ Creates a new #GtkAccelLabel.
 @Returns: a new #GtkAccelLabel.
 
 
-<!-- ##### FUNCTION gtk_accel_label_get_accel_object ##### -->
+<!-- ##### FUNCTION gtk_accel_label_get_accel_widget ##### -->
 <para>
 
 </para>
@@ -103,24 +103,7 @@ Creates a new #GtkAccelLabel.
 @Returns: 
 
 
-<!-- ##### FUNCTION gtk_accel_label_set_accel_object ##### -->
-<para>
-
-</para>
-
-@accel_label: 
-@accel_object: 
-
-
-<!-- ##### MACRO gtk_accel_label_get_accel_widget ##### -->
-<para>
-
-</para>
-
-@accel_label:
-
-
-<!-- ##### MACRO gtk_accel_label_set_accel_widget ##### -->
+<!-- ##### FUNCTION gtk_accel_label_set_accel_widget ##### -->
 <para>
 Sets the widget whose accelerators are to be shown.
 </para>
@@ -151,8 +134,13 @@ accelerators are added or removed from the associated widget.
 @Returns: always returns %FALSE.
 
 
-<!-- ##### ARG GtkAccelLabel:accel-object ##### -->
+<!-- ##### ARG GtkAccelLabel:accel-closure ##### -->
 <para>
 
 </para>
 
+<!-- ##### ARG GtkAccelLabel:accel-widget ##### -->
+<para>
+The widget whose accelerators are to be shown by the #GtkAccelLabel.
+</para>
+
index 73907ce28921525ffb1b950c9d5177e23cb65adf..5bb58e122910eef6efcafd7f042fb5781135cad8 100644 (file)
@@ -225,7 +225,7 @@ time.
 
 </para>
 
-@colorsel:
+@colorsel: 
 @color: 
 
 
@@ -234,8 +234,8 @@ time.
 
 </para>
 
-@colorsel:
-@color:
+@colorsel: 
+@color: 
 
 
 <!-- ##### SIGNAL GtkColorSelection::color-changed ##### -->
index 8034f9cb780987e43680885b383747a8ff6d59ab..4f6ed7b6fe8220bb476fa56c65c9440c3683184d 100644 (file)
@@ -178,7 +178,7 @@ worried about differences in case.
 </para>
 
 @combo: a #GtkCombo.
-@val: %TRUE if the text in the list items is case sensitive. 
+@val: %TRUE if the text in the list items is case sensitive.
 
 
 <!-- ##### FUNCTION gtk_combo_set_item_string ##### -->
index f677af775db1d2b92a071a534e0df712f37e4e95..7eb449fe1ad852366f72a2c4b9aab78b1c7021df 100644 (file)
@@ -169,7 +169,7 @@ Creates a new dialog box. Widgets should not be packed into this #GtkWindow
 directly, but into the vbox and action_area, as described above. 
 </para>
 
-@Returns: a new #GtkDialog. 
+@Returns: a new #GtkDialog.
 
 
 <!-- ##### FUNCTION gtk_dialog_new_with_buttons ##### -->
index 6c19bccb7371319e81219b2842082adf5ea88d06..304ae8d02e6b9492d4186d62497ebd906ffc0fb9 100644 (file)
@@ -20,7 +20,6 @@ Public enumerated types used throughout GTK+.
 </para>
 
 @GTK_ACCEL_VISIBLE: 
-@GTK_ACCEL_SIGNAL_VISIBLE: 
 @GTK_ACCEL_LOCKED: 
 @GTK_ACCEL_MASK: 
 
index abda892595f0435f91ce83eab19df0af73752262..57c1fd8f71f79c0d8c6d58c3f7baf17be4cf81ed 100644 (file)
@@ -84,11 +84,6 @@ GtkItemFactory
 </para>
 
 @path: 
-@accelerator_key: 
-@accelerator_mods: 
-@modified: 
-@in_propagation: 
-@dummy: 
 @widgets: 
 
 <!-- ##### FUNCTION gtk_item_factory_new ##### -->
@@ -113,30 +108,6 @@ GtkItemFactory
 @accel_group: 
 
 
-<!-- ##### FUNCTION gtk_item_factory_parse_rc ##### -->
-<para>
-
-</para>
-
-@file_name: 
-
-
-<!-- ##### FUNCTION gtk_item_factory_parse_rc_string ##### -->
-<para>
-
-</para>
-
-@rc_string: 
-
-
-<!-- ##### FUNCTION gtk_item_factory_parse_rc_scanner ##### -->
-<para>
-
-</para>
-
-@scanner: 
-
-
 <!-- ##### FUNCTION gtk_item_factory_add_foreign ##### -->
 <para>
 
@@ -207,36 +178,6 @@ GtkItemFactory
 @Returns: 
 
 
-<!-- ##### FUNCTION gtk_item_factory_dump_items ##### -->
-<para>
-
-</para>
-
-@path_pspec: 
-@modified_only: 
-@print_func: 
-@func_data: 
-
-
-<!-- ##### FUNCTION gtk_item_factory_dump_rc ##### -->
-<para>
-
-</para>
-
-@file_name: 
-@path_pspec: 
-@modified_only: 
-
-
-<!-- ##### FUNCTION gtk_item_factory_print_func ##### -->
-<para>
-
-</para>
-
-@FILE_pointer: 
-@string: 
-
-
 <!-- ##### FUNCTION gtk_item_factory_create_item ##### -->
 <para>
 
index 8bb20423d861469c6505926ac9b8efed79fc6425..eb37062f02d284989b271bf54174ecb0dc313070 100644 (file)
@@ -96,9 +96,9 @@ Creates a new #GtkMenu.
 Adds a new #GtkMenuItem to the end of the menu's item list.
 </para>
 
-<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
+<!-- # Unused Parameters # -->
 @m: 
 @c: 
 
@@ -108,9 +108,9 @@ Adds a new #GtkMenuItem to the end of the menu's item list.
 Adds a new #GtkMenuItem to the beginning of the menu's item list.
 </para>
 
-<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
+<!-- # Unused Parameters # -->
 @menu_child: 
 @m: 
 @c: 
@@ -122,10 +122,10 @@ Adds a new #GtkMenuItem to the menu's item list at the position
 indicated by @position. 
 </para>
 
-<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
 @pos: 
+<!-- # Unused Parameters # -->
 @position: The position in the item list where @child is added.
 Positions are numbered from 0 to n-1.
 
@@ -162,6 +162,9 @@ at the current pointer position.
 <!-- ##### FUNCTION gtk_menu_set_accel_group ##### -->
 <para>
 Set the #GtkAccelGroup which holds global accelerators for the menu.
+This accelerator group needs to also be added to all windows that
+this menu is being used in with gtk_window_add_accel_group(), in order
+for those windows to support all the accelerators contained in this group.
 </para>
 
 @menu: a #GtkMenu.
@@ -178,6 +181,15 @@ See gtk_menu_set_accel_group().
 @Returns: the #GtkAccelGroup associated with the menu.
 
 
+<!-- ##### FUNCTION gtk_menu_set_accel_path ##### -->
+<para>
+
+</para>
+
+@menu: 
+@accel_path: 
+
+
 <!-- ##### FUNCTION gtk_menu_set_title ##### -->
 <para>
 Sets the title string for the menu.  The title is displayed when the menu
index 76b4e863985086bdf21a70b9753ed33c3e382c8f..d65e13a75e9febcb16725bfb403ef1f6fa67fc3c 100644 (file)
@@ -83,6 +83,15 @@ Sets the widget submenu, or changes it.
 @submenu: the submenu
 
 
+<!-- ##### FUNCTION gtk_menu_item_set_accel_path ##### -->
+<para>
+
+</para>
+
+@menu_item: 
+@accel_path: 
+
+
 <!-- ##### FUNCTION gtk_menu_item_remove_submenu ##### -->
 <para>
 Removes the widget's submenu.
index f3a7e01e0916217162cc1784acd324d9ca783cef..95369862de4facac323ae12c9f453e6900556445 100644 (file)
@@ -112,6 +112,9 @@ Old name for gtk_paned_set_handle_size()
 Old name for gtk_paned_set_gutter_size()
 </para>
 
+@p: 
+@s: 
+
 
 <!-- ##### FUNCTION gtk_paned_pack1 ##### -->
 <para>
index 9ee5eb8542ad315d24a5e15300bf9cc8776daf86..74562454d886ff6b510becc788b55b1173aac4ec 100644 (file)
@@ -47,8 +47,8 @@ Widgets can be visibly grouped by adding gaps between widgets using gtk_toolbar_
 to a #GtkToolbar.
 </para>
 
-@GTK_TOOLBAR_CHILD_SPACE: a space in the style of the toolbar's #GtkToolbarSpaceStyle. 
-@GTK_TOOLBAR_CHILD_BUTTON: a #GtkButton. 
+@GTK_TOOLBAR_CHILD_SPACE: a space in the style of the toolbar's #GtkToolbarSpaceStyle.
+@GTK_TOOLBAR_CHILD_BUTTON: a #GtkButton.
 @GTK_TOOLBAR_CHILD_TOGGLEBUTTON: a #GtkToggleButton.
 @GTK_TOOLBAR_CHILD_RADIOBUTTON: a #GtkRadioButton.
 @GTK_TOOLBAR_CHILD_WIDGET: a standard #GtkWidget.
index 842769a8994f8d3a40b171cee01bc06fa88cf3a7..9414655b6bcbb17e4124a0f222c3bfb3655d4963 100644 (file)
@@ -43,6 +43,7 @@ GtkTreeView drag-and-drop
 </para>
 
 @g_iface: 
+@row_draggable: 
 @drag_data_get: 
 @drag_data_delete: 
 
index 3234cc1c0beccfc08076f46173ae6907dffb6288..b8480449e853826f0932dec1d0fc81d9d57fceed 100644 (file)
@@ -49,18 +49,6 @@ GtkTreeView
 @Returns: 
 
 
-<!-- ##### USER_FUNCTION GtkTreeViewDraggableFunc ##### -->
-<para>
-
-</para>
-
-@tree_view: 
-@context: 
-@path: 
-@user_data: 
-@Returns: 
-
-
 <!-- ##### USER_FUNCTION GtkTreeViewMappingFunc ##### -->
 <para>
 
@@ -71,19 +59,6 @@ GtkTreeView
 @user_data: 
 
 
-<!-- ##### USER_FUNCTION GtkTreeViewDroppableFunc ##### -->
-<para>
-
-</para>
-
-@tree_view: 
-@context: 
-@path: 
-@pos: 
-@user_data: 
-@Returns: 
-
-
 <!-- ##### USER_FUNCTION GtkTreeViewSearchEqualFunc ##### -->
 <para>
 
@@ -559,33 +534,6 @@ GtkTreeView
 @wy: 
 
 
-<!-- ##### FUNCTION gtk_tree_view_set_rows_drag_source ##### -->
-<para>
-
-</para>
-
-@tree_view: 
-@start_button_mask: 
-@targets: 
-@n_targets: 
-@actions: 
-@row_draggable_func: 
-@user_data: 
-
-
-<!-- ##### FUNCTION gtk_tree_view_set_rows_drag_dest ##### -->
-<para>
-
-</para>
-
-@tree_view: 
-@targets: 
-@n_targets: 
-@actions: 
-@location_droppable_func: 
-@user_data: 
-
-
 <!-- ##### FUNCTION gtk_tree_view_unset_rows_drag_source ##### -->
 <para>
 
index 4781aee5fd41d3e2fdddd63417e56c3116267be6..76769b73b5220e8e7f73b711abaaf539ff084a54 100644 (file)
@@ -523,27 +523,6 @@ GtkWidget
 
 </para>
 
-@widget: 
-@accel_group: 
-@accel_key: 
-@accel_mods: 
-
-
-<!-- ##### FUNCTION gtk_widget_remove_accelerators ##### -->
-<para>
-
-</para>
-
-@widget: 
-@accel_signal: 
-@visible_only: 
-
-
-<!-- ##### FUNCTION gtk_widget_accelerator_signal ##### -->
-<para>
-
-</para>
-
 @widget: 
 @accel_group: 
 @accel_key: 
@@ -1000,14 +979,6 @@ GtkWidget
 @Returns: 
 
 
-<!-- ##### FUNCTION gtk_widget_lock_accelerators ##### -->
-<para>
-
-</para>
-
-@widget: 
-
-
 <!-- ##### FUNCTION gtk_widget_modify_style ##### -->
 <para>
 
@@ -1207,23 +1178,6 @@ GtkWidget
 @Returns: 
 
 
-<!-- ##### FUNCTION gtk_widget_unlock_accelerators ##### -->
-<para>
-
-</para>
-
-@widget: 
-
-
-<!-- ##### FUNCTION gtk_widget_accelerators_locked ##### -->
-<para>
-
-</para>
-
-@widget: 
-@Returns: 
-
-
 <!-- ##### FUNCTION gtk_widget_mnemonic_activate ##### -->
 <para>
 
@@ -1456,17 +1410,12 @@ GtkWidget
 @requisition: 
 
 
-<!-- ##### SIGNAL GtkWidget::add-accelerator ##### -->
+<!-- ##### SIGNAL GtkWidget::accel-closures-changed ##### -->
 <para>
 
 </para>
 
 @widget: the object which received the signal.
-@accel_signal_id: 
-@accel_group: 
-@accel_key: 
-@accel_mods: 
-@accel_flags: 
 
 <!-- ##### SIGNAL GtkWidget::button-press-event ##### -->
 <para>
@@ -1834,16 +1783,6 @@ a widget changes from un-anchored to anchored or vice-versa.
 
 @widget: the object which received the signal.
 
-<!-- ##### SIGNAL GtkWidget::remove-accelerator ##### -->
-<para>
-
-</para>
-
-@widget: the object which received the signal.
-@accel_group: 
-@accel_key: 
-@accel_mods: 
-
 <!-- ##### SIGNAL GtkWidget::scroll-event ##### -->
 <para>
 
index 66ea51639941f59a27d9253cd15669a3c40dd667..b8111b43623a78a6e3aad49f260531a754738ce0 100644 (file)
@@ -694,6 +694,13 @@ it's larger
 @height: 
 
 
+<!-- ##### SIGNAL GtkWindow::accels-changed ##### -->
+<para>
+
+</para>
+
+@window: the object which received the signal.
+
 <!-- ##### SIGNAL GtkWindow::activate-default ##### -->
 <para>
 
index bef5917e0ab8bc7592ddfcd4496c330f8f147b42..bbe5fa6fe230e668ecfa5547738fd8847f4f9f28 100644 (file)
@@ -86,6 +86,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
        gtk.h                   \
        gtkaccelgroup.h         \
        gtkaccellabel.h         \
+       gtkaccelmap.h           \
        gtkaccessible.h         \
        gtkadjustment.h         \
        gtkalignment.h          \
@@ -244,6 +245,7 @@ gtk_private_h_sources = @STRIP_BEGIN@ \
 # GTK+ C sources to build the library from
 gtk_c_sources = @STRIP_BEGIN@   \
        gtkaccelgroup.c         \
+       gtkaccelmap.c           \
        gtkaccellabel.c         \
        gtkaccessible.c         \
        gtkadjustment.c         \
index d7d802973ddb4f72e006d84df0e3e3eaa4087ffc..9a9016e64f0dce43c16656cf4934cab4d10bc977 100644 (file)
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -31,6 +31,7 @@
 #include <gdk/gdk.h>
 #include <gtk/gtkaccelgroup.h>
 #include <gtk/gtkaccellabel.h>
+#include <gtk/gtkaccelmap.h>
 #include <gtk/gtkaccessible.h>
 #include <gtk/gtkadjustment.h>
 #include <gtk/gtkalignment.h>
index 0464ecd7ce0370c54285044c250a9a61a723cd92..a8c36b76436fe12227e55ccda93559ed32e18ec0 100644 (file)
@@ -1,8 +1,5 @@
 /* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GtkAccelGroup: Accelerator manager for GtkObjects.
- * Copyright (C) 1998 Tim Janik
+ * Copyright (C) 1998, 2001 Tim Janik
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * files for a list of changes.  These files are distributed with
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
-
-#include <ctype.h>
-#include <string.h>
 #include "gtkaccelgroup.h"
+#include "gtkaccelmap.h"
 #include "gdk/gdkkeysyms.h"
 #include "gtksignal.h"
-#include "gtkwidget.h"
-
-
-/* --- signals --- */
-typedef void (*GtkSignalAddAccelerator)           (GObject         *object,
-                                           guint            accel_signal_id,
-                                           GtkAccelGroup   *accel_group,
-                                           guint            accel_key,
-                                           GdkModifierType  accel_mods,
-                                           GtkAccelFlags    accel_flags,
-                                           gpointer         func_data);
-typedef void (*GtkSignalRemoveAccelerator) (GObject        *object,
-                                           GtkAccelGroup   *accel_group,
-                                           guint            accel_key,
-                                           GdkModifierType  accel_mods,
-                                           gpointer         func_data);
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* --- prototypes --- */
+static void gtk_accel_group_class_init (GtkAccelGroupClass     *class);
+static void gtk_accel_group_init       (GtkAccelGroup          *accel_group);
+static void gtk_accel_group_finalize   (GObject                *object);
+
 
 /* --- variables --- */
-static GtkAccelGroup   *default_accel_group = NULL;
+static GObjectClass     *parent_class = NULL;
+static guint            signal_accel_activate = 0;
+static guint            signal_accel_changed = 0;
+static guint            quark_acceleratable_groups = 0;
 static guint            default_accel_mod_mask = (GDK_SHIFT_MASK |
                                                   GDK_CONTROL_MASK |
                                                   GDK_MOD1_MASK);
-static const gchar     *accel_groups_key = "gtk-accel-groups";
-static guint            accel_groups_key_id = 0;
-static const gchar     *accel_entries_key = "gtk-accel-entries";
-static guint            accel_entries_key_id = 0;
-static GHashTable      *accel_entry_hash_table = NULL;
-static GMemChunk       *accel_entries_mem_chunk = NULL;
-
-static GObjectClass     *parent_class = NULL;
 
 
 /* --- functions --- */
-static gboolean
-gtk_accel_entries_equal (gconstpointer a,
-                        gconstpointer b)
-{
-  const GtkAccelEntry *e1;
-  const GtkAccelEntry *e2;
-  
-  e1 = a;
-  e2 = b;
-  
-  return ((e1->accel_group == e2->accel_group) &&
-         (e1->accelerator_key == e2->accelerator_key) &&
-         (e1->accelerator_mods == e2->accelerator_mods));
-}
-
-static guint
-gtk_accel_entries_hash (gconstpointer a)
-{
-  const GtkAccelEntry *e;
-  guint h;
-  
-  e = a;
-  
-  h = (gulong) e->accel_group;
-  h ^= e->accelerator_key << 16;
-  h ^= e->accelerator_key >> 16;
-  h ^= e->accelerator_mods;
-  
-  return h;
-}
-
-static void gtk_accel_group_class_init (GObjectClass *class);
-static void gtk_accel_group_init (GtkAccelGroup *accel_group);
-
+/**
+ * gtk_accel_map_change_entry
+ * @returns: the type ID for accelerator groups
+ */
 GType
 gtk_accel_group_get_type (void)
 {
@@ -106,15 +61,14 @@ gtk_accel_group_get_type (void)
 
   if (!object_type)
     {
-      static const GTypeInfo object_info =
-      {
+      static const GTypeInfo object_info = {
        sizeof (GtkAccelGroupClass),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gtk_accel_group_class_init,
        NULL,   /* clas_finalize */
        NULL,   /* class_data */
-       sizeof(GtkAccelGroup),
+       sizeof (GtkAccelGroup),
        0,      /* n_preallocs */
        (GInstanceInitFunc) gtk_accel_group_init,
       };
@@ -127,120 +81,90 @@ gtk_accel_group_get_type (void)
   return object_type;
 }
 
-static void
-gtk_accel_group_finalize (GObject *object)
+static gboolean
+accel_activate_accumulator (GSignalInvocationHint *ihint,
+                           GValue                *return_accu,
+                           const GValue          *handler_return,
+                           gpointer               data)
 {
-  GtkAccelGroup *accel_group = GTK_ACCEL_GROUP(object);
+  gboolean continue_emission;
+  gboolean handler_val;
 
-  if (accel_group == default_accel_group)
-    g_warning (G_STRLOC "default accel group should not be finalized");
+  /* handler returns whether the accelerator was handled */
+  handler_val = g_value_get_boolean (handler_return);
 
-  (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
+  /* record that as result for this emission */
+  g_value_set_boolean (return_accu, handler_val);
 
-static void
-gtk_accel_group_class_init (GObjectClass *class)
-{
-  parent_class = g_type_class_ref (G_TYPE_OBJECT);
+  /* don't continue if accelerator was handled */
+  continue_emission = !handler_val;
 
-  class->finalize = gtk_accel_group_finalize;
+  return continue_emission;
 }
 
 static void
-gtk_accel_group_init (GtkAccelGroup *accel_group)
+gtk_accel_group_class_init (GtkAccelGroupClass *class)
 {
-  if (!accel_groups_key_id)
-    {
-      accel_groups_key_id = g_quark_from_static_string (accel_groups_key);
-      accel_entries_key_id = g_quark_from_static_string (accel_entries_key);
-      
-      accel_entry_hash_table = g_hash_table_new (gtk_accel_entries_hash,
-                                                gtk_accel_entries_equal);
-      
-      accel_entries_mem_chunk = g_mem_chunk_create (GtkAccelEntry, 64, G_ALLOC_AND_FREE);
-    }
-
-  accel_group->lock_count = 0;
-  accel_group->modifier_mask = gtk_accelerator_get_default_mod_mask ();
-  accel_group->attach_objects = NULL;
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  parent_class = g_type_class_peek_parent (class);
+
+  quark_acceleratable_groups = g_quark_from_static_string ("gtk-acceleratable-accel-groups");
+
+  object_class->finalize = gtk_accel_group_finalize;
+
+  class->accel_changed = NULL;
+  signal_accel_activate = g_signal_new ("accel_activate",
+                                       G_OBJECT_CLASS_TYPE (class),
+                                       G_SIGNAL_DETAILED,
+                                       0,
+                                       accel_activate_accumulator, NULL,
+                                       gtk_marshal_BOOLEAN__OBJECT_UINT_UINT,
+                                       G_TYPE_BOOLEAN, 3, G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_UINT);
+  signal_accel_changed = g_signal_new ("accel_changed",
+                                      G_OBJECT_CLASS_TYPE (class),
+                                      G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
+                                      G_STRUCT_OFFSET (GtkAccelGroupClass, accel_changed),
+                                      NULL, NULL,
+                                      gtk_marshal_VOID__UINT_UINT_BOXED,
+                                      G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_CLOSURE);
 }
 
-/**
- * gtk_accel_group_new:
- * 
- * Creates a new #GtkAccelGroup. 
- * 
- * Return value: a new #GtkAccelGroup
- **/
-GtkAccelGroup*
-gtk_accel_group_new (void)
+static void
+gtk_accel_group_finalize (GObject *object)
 {
-  GtkAccelGroup *accel_group;
+  GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (object);
 
-  accel_group = (GtkAccelGroup *)g_object_new(GTK_TYPE_ACCEL_GROUP, NULL);
+  g_free (accel_group->priv_accels);
 
-  return accel_group;
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-/**
- * gtk_accel_group_get_default:
- * 
- * Gets the global default accelerator group; this is a fallback
- * used for all objects when gtk_accel_groups_activate() is called
- * on them. As such it's probably not appropriate for most uses.
- * (Accelerators are normally specific to a document window or the
- * like, rather than global to an application.)
- *
- * The returned value does not have its reference count incremented,
- * and should not be unreferenced.
- * 
- * Return value: the default accelerator group
- **/
-GtkAccelGroup*
-gtk_accel_group_get_default (void)
+static void
+gtk_accel_group_init (GtkAccelGroup *accel_group)
 {
-  if (!default_accel_group)
-    default_accel_group = gtk_accel_group_new ();
-  
-  return default_accel_group;
+  accel_group->lock_count = 0;
+  accel_group->modifier_mask = gtk_accelerator_get_default_mod_mask ();
+  accel_group->acceleratables = NULL;
+  accel_group->n_accels = 0;
+  accel_group->priv_accels = NULL;
 }
 
 /**
- * gtk_accel_group_ref:
- * @accel_group: a #GtkAccelGroup
+ * gtk_accel_group_new
+ * @returns: a new #GtkAccelGroup object
  * 
- * This is simply equivalent to g_object_ref (G_OBJECT (@accel_group)),
- * and exists for historical reasons only.
- * 
- * Return value: @accel_group
- **/
+ * Creates a new #GtkAccelGroup. 
+ */
 GtkAccelGroup*
-gtk_accel_group_ref (GtkAccelGroup     *accel_group)
-{
-  g_return_val_if_fail (GTK_IS_ACCEL_GROUP(accel_group), NULL);
-
-  return (GtkAccelGroup *)g_object_ref(accel_group);
-}
-
-/**
- * gtk_accel_group_unref:
- * @accel_group: a #GtkAccelGroup
- * 
- * This is simply equivalent to g_object_unref (G_OBJECT (@accel_group)),
- * and exists for historical reasons only.
- * 
- **/
-void
-gtk_accel_group_unref (GtkAccelGroup  *accel_group)
+gtk_accel_group_new (void)
 {
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-  
-  g_object_unref(accel_group);
+  return g_object_new (GTK_TYPE_ACCEL_GROUP, NULL);
 }
 
 static void
-gtk_accel_group_object_destroy (GSList *free_list,
-                               GObject *where_the_object_was)
+accel_group_weak_ref_detach (GSList  *free_list,
+                            GObject *stale_object)
 {
   GSList *slist;
   
@@ -249,646 +173,488 @@ gtk_accel_group_object_destroy (GSList *free_list,
       GtkAccelGroup *accel_group;
       
       accel_group = slist->data;
-      accel_group->attach_objects = g_slist_remove (accel_group->attach_objects, where_the_object_was);
+      accel_group->acceleratables = g_slist_remove (accel_group->acceleratables, stale_object);
       g_object_unref (accel_group);
     }
   g_slist_free (free_list);
 }
 
-/**
- * gtk_accel_group_attach:
- * @accel_group: a #GtkAccelGroup
- * @object: object to attach accelerators to
- *
- * Associate @accel_group with @object, such that calling
- * gtk_accel_groups_activate() on @object will activate accelerators
- * in @accel_group.
- *
- * After calling this function, you still own a reference to both
- * @accel_group and @object; gtk_accel_group_attach() will not
- * "adopt" a reference to either one.
- * 
- **/
 void
-gtk_accel_group_attach (GtkAccelGroup  *accel_group,
-                       GObject         *object)
+_gtk_accel_group_attach (GtkAccelGroup *accel_group,
+                        GObject       *object)
 {
   GSList *slist;
   
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
   g_return_if_fail (G_IS_OBJECT (object));
-  g_return_if_fail (g_slist_find (accel_group->attach_objects, object) == NULL);
+  g_return_if_fail (g_slist_find (accel_group->acceleratables, object) == NULL);
   
-  accel_group->attach_objects = g_slist_prepend (accel_group->attach_objects, object);
   g_object_ref (accel_group);
-  slist = g_object_get_qdata (object, accel_groups_key_id);
+  accel_group->acceleratables = g_slist_prepend (accel_group->acceleratables, object);
+  slist = g_object_get_qdata (object, quark_acceleratable_groups);
   if (slist)
-    g_object_weak_unref(object,
-                       (GWeakNotify)gtk_accel_group_object_destroy,
-                       slist);
+    g_object_weak_unref (object,
+                        (GWeakNotify) accel_group_weak_ref_detach,
+                        slist);
   slist = g_slist_prepend (slist, accel_group);
-  g_object_set_qdata (object, accel_groups_key_id, slist);
-  g_object_weak_ref(object,
-                   (GWeakNotify)gtk_accel_group_object_destroy,
-                   slist);
+  g_object_set_qdata (object, quark_acceleratable_groups, slist);
+  g_object_weak_ref (object,
+                    (GWeakNotify) accel_group_weak_ref_detach,
+                    slist);
 }
 
-/**
- * gtk_accel_group_detach:
- * @accel_group: a #GtkAccelGroup
- * @object: a #GObject
- *
- * Reverses the effects of gtk_accel_group_attach().
- * 
- **/
 void
-gtk_accel_group_detach (GtkAccelGroup  *accel_group,
-                       GObject         *object)
+_gtk_accel_group_detach (GtkAccelGroup *accel_group,
+                        GObject       *object)
 {
   GSList *slist;
   
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
   g_return_if_fail (G_IS_OBJECT (object));
-  g_return_if_fail (g_slist_find (accel_group->attach_objects, object) != NULL);
+  g_return_if_fail (g_slist_find (accel_group->acceleratables, object) != NULL);
   
-  accel_group->attach_objects = g_slist_remove (accel_group->attach_objects, object);
-  g_object_unref (accel_group);
-  slist = g_object_get_qdata (object, accel_groups_key_id);
-  g_object_weak_unref(object,
-                     (GWeakNotify)gtk_accel_group_object_destroy,
-                     slist);
+  accel_group->acceleratables = g_slist_remove (accel_group->acceleratables, object);
+  slist = g_object_get_qdata (object, quark_acceleratable_groups);
+  g_object_weak_unref (object,
+                      (GWeakNotify) accel_group_weak_ref_detach,
+                      slist);
   slist = g_slist_remove (slist, accel_group);
-  g_object_set_qdata (object, accel_groups_key_id, slist);
+  g_object_set_qdata (object, quark_acceleratable_groups, slist);
   if (slist)
-    g_object_weak_ref(object,
-                     (GWeakNotify)gtk_accel_group_object_destroy,
-                     slist);
+    g_object_weak_ref (object,
+                      (GWeakNotify) accel_group_weak_ref_detach,
+                      slist);
+  g_object_unref (accel_group);
+}
+
+GSList*
+gtk_accel_groups_from_acceleratable (GObject *object)
+{
+  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+  
+  return g_object_get_qdata (object, quark_acceleratable_groups);
+}
+
+GtkAccelKey*
+gtk_accel_group_find (GtkAccelGroup  *accel_group,
+                     gboolean (*find_func) (GtkAccelKey *key,
+                                            GClosure    *closure,
+                                            gpointer     data),
+                     gpointer        data)
+{
+  GtkAccelKey *key = NULL;
+  guint i;
+
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+  g_return_val_if_fail (find_func != NULL, NULL);
+
+  g_object_ref (accel_group);
+  for (i = 0; i < accel_group->n_accels; i++)
+    if (find_func (&accel_group->priv_accels[i].key,
+                  accel_group->priv_accels[i].closure,
+                  data))
+      {
+       key = &accel_group->priv_accels[i].key;
+       break;
+      }
+  g_object_unref (accel_group);
+
+  return key;
 }
 
 /**
- * gtk_accel_group_lock:
+ * gtk_accel_group_lock
  * @accel_group: a #GtkAccelGroup
  * 
- * Prevents the addition of new accelerators to @accel_group.
- * Primarily used to avoid the "dynamic accelerator editing" feature
- * of #GtkMenu.
+ * Locking an acelerator group prevents the accelerators contained
+ * within it to be changed during runtime. Refer to
+ * gtk_accel_map_change_entry() about runtime accelerator changes.
  *
  * If called more than once, @accel_group remains locked until
  * gtk_accel_group_unlock() has been called an equivalent number
  * of times.
- * 
- **/
+ */
 void
-gtk_accel_group_lock (GtkAccelGroup     *accel_group)
+gtk_accel_group_lock (GtkAccelGroup *accel_group)
 {
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
   
   accel_group->lock_count += 1;
 }
 
 /**
- * gtk_accel_group_unlock:
+ * gtk_accel_group_unlock
  * @accel_group: a #GtkAccelGroup
  * 
- * Allows the addition of new accelerators to @accel_group.
- * Primarily used to enable the "dynamic accelerator editing" feature
- * of #GtkMenu.
- * 
- **/
+ * This function undoes the last call to gtk_accel_group_lock()
+ * on this @accel_group.
+ */
 void
-gtk_accel_group_unlock (GtkAccelGroup  *accel_group)
+gtk_accel_group_unlock (GtkAccelGroup *accel_group)
 {
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-  
-  if (accel_group->lock_count)
-    accel_group->lock_count -= 1;
-}
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+  g_return_if_fail (accel_group->lock_count > 0);
 
-static GtkAccelEntry*
-gtk_accel_group_lookup (GtkAccelGroup  *accel_group,
-                       guint            accel_key,
-                       GdkModifierType  accel_mods)
-{
-  GtkAccelEntry key_entry = { 0 };
-  
-  key_entry.accel_group = accel_group;
-  key_entry.accelerator_key = gdk_keyval_to_lower (accel_key);
-  key_entry.accelerator_mods = accel_mods & accel_group->modifier_mask;
-  
-  return g_hash_table_lookup (accel_entry_hash_table, &key_entry);
+  accel_group->lock_count -= 1;
 }
 
-/**
- * gtk_accel_group_activate:
- * @accel_group: a #GtkAccelGroup
- * @accel_key: keyval from a key event
- * @accel_mods: modifier mask from a key event
- *
- * Checks whether a key event matches an accelerator in @accel_group;
- * if so, activates the accelerator, and returns %TRUE. Returns
- * %FALSE if no match.
- *
- * gtk_accel_groups_activate() should normally be used instead of
- * this function.
- * 
- * Return value: %TRUE if an accelerator was activated
- **/
-gboolean
-gtk_accel_group_activate (GtkAccelGroup         *accel_group,
-                         guint           accel_key,
-                         GdkModifierType accel_mods)
+static void
+accel_tag_func (gpointer  data,
+               GClosure *closure)
 {
-  GtkAccelEntry *entry;
-  
-  g_return_val_if_fail (GTK_IS_ACCEL_GROUP(accel_group), FALSE);
-  
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (entry && entry->signal_id &&
-      (!GTK_IS_WIDGET (entry->object) || GTK_WIDGET_IS_SENSITIVE (entry->object)))
-    {
-      g_signal_emit (entry->object, entry->signal_id, 0);
-      return TRUE;
-    }
-  return FALSE;
+  /* GtkAccelGroup *accel_group = data; */
 }
 
-/**
- * gtk_accel_groups_activate:
- * @object: a #GObject
- * @accel_key: accelerator keyval from a key event
- * @accel_mods: keyboard state mask from a key event
- * 
- * Finds the first accelerator in any #GtkAccelGroup attached
- * to @object that matches @accel_key and @accel_mods, and
- * activates that accelerator. If no accelerators are found
- * in groups attached to @object, this function also tries
- * the default #GtkAccelGroup (see gtk_accel_group_get_default()).
- * If an accelerator is activated, returns %TRUE, otherwise
- * %FALSE.
- * 
- * Return value: %TRUE if an accelerator was activated
- **/
-gboolean
-gtk_accel_groups_activate (GObject         *object,
-                          guint             accel_key,
-                          GdkModifierType   accel_mods)
+static int
+bsearch_compare_accels (const void *d1,
+                       const void *d2)
 {
-  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-  
-  if (gtk_accelerator_valid (accel_key, accel_mods))
-    {
-      GSList *slist;
-      
-      for (slist = gtk_accel_groups_from_object (object); slist; slist = slist->next)
-       if (gtk_accel_group_activate (slist->data, accel_key, accel_mods))
-         return TRUE;
-      return gtk_accel_group_activate (gtk_accel_group_get_default (), accel_key, accel_mods);
-    }
-  
-  return FALSE;
+  const GtkAccelGroupEntry *entry1 = d1;
+  const GtkAccelGroupEntry *entry2 = d2;
+
+  if (entry1->key.accel_key == entry2->key.accel_key)
+    return entry1->key.accel_mods < entry2->key.accel_mods ? -1 : entry1->key.accel_mods > entry2->key.accel_mods;
+  else
+    return entry1->key.accel_key < entry2->key.accel_key ? -1 : 1;
 }
 
-void
-gtk_accel_group_lock_entry (GtkAccelGroup       *accel_group,
-                           guint                 accel_key,
-                           GdkModifierType       accel_mods)
+static void
+quick_accel_add (GtkAccelGroup  *accel_group,
+                guint           accel_key,
+                GdkModifierType accel_mods,
+                GtkAccelFlags   accel_flags,
+                GClosure       *closure,
+                GQuark          path_quark)
 {
-  GtkAccelEntry *entry;
-  
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-  
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (entry)
-    entry->accel_flags |= GTK_ACCEL_LOCKED;
+  guint pos, i = accel_group->n_accels++;
+  GtkAccelGroupEntry key;
+
+  key.key.accel_key = accel_key;
+  key.key.accel_mods = accel_mods;
+  for (pos = 0; pos < i; pos++)
+    if (bsearch_compare_accels (&key, accel_group->priv_accels + pos) < 0)
+      break;
+  accel_group->priv_accels = g_renew (GtkAccelGroupEntry, accel_group->priv_accels, accel_group->n_accels);
+  g_memmove (accel_group->priv_accels + pos + 1, accel_group->priv_accels + pos,
+            (i - pos) * sizeof (accel_group->priv_accels[0]));
+  accel_group->priv_accels[pos].key.accel_key = accel_key;
+  accel_group->priv_accels[pos].key.accel_mods = accel_mods;
+  accel_group->priv_accels[pos].key.accel_flags = accel_flags;
+  accel_group->priv_accels[pos].closure = g_closure_ref (closure);
+  accel_group->priv_accels[pos].accel_path_quark = path_quark;
+  g_closure_sink (closure);
+
+  /* tag closure for backwards lookup */
+  g_closure_add_invalidate_notifier (closure, accel_group, accel_tag_func);
 }
 
-void
-gtk_accel_group_unlock_entry (GtkAccelGroup    *accel_group,
-                             guint              accel_key,
-                             GdkModifierType    accel_mods)
+static GtkAccelGroupEntry*
+quick_accel_find (GtkAccelGroup  *accel_group,
+                 guint           accel_key,
+                 GdkModifierType accel_mods,
+                 guint          *count_p)
 {
-  GtkAccelEntry *entry;
-  
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
+  GtkAccelGroupEntry *entry;
+  GtkAccelGroupEntry key;
+
+  if (!accel_group->n_accels)
+    return NULL;
+
+  key.key.accel_key = accel_key;
+  key.key.accel_mods = accel_mods;
+  entry = bsearch (&key, accel_group->priv_accels, accel_group->n_accels,
+                  sizeof (accel_group->priv_accels[0]), bsearch_compare_accels);
   
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (entry)
-    entry->accel_flags &= ~GTK_ACCEL_LOCKED;
+  if (!entry)
+    return NULL;
+
+  /* step back to the first member */
+  for (; entry > accel_group->priv_accels; entry--)
+    if (entry[-1].key.accel_key != accel_key ||
+       entry[-1].key.accel_mods != accel_mods)
+      break;
+  /* count equal members */
+  for (*count_p = 0; entry + *count_p < accel_group->priv_accels + accel_group->n_accels; (*count_p)++)
+    if (entry[*count_p].key.accel_key != accel_key ||
+       entry[*count_p].key.accel_mods != accel_mods)
+      break;
+  return entry;
 }
 
-GtkAccelEntry*
-gtk_accel_group_get_entry (GtkAccelGroup    *accel_group,
-                          guint             accel_key,
-                          GdkModifierType   accel_mods)
+static GSList*
+quick_accel_remove (GtkAccelGroup  *accel_group,
+                   guint           accel_key,
+                   GdkModifierType accel_mods)
 {
-  g_return_val_if_fail (GTK_IS_ACCEL_GROUP(accel_group), 0);
-  
-  return gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
+  guint i, n;
+  GtkAccelGroupEntry *entry = quick_accel_find (accel_group, accel_key, accel_mods, &n);
+  guint pos = entry - accel_group->priv_accels;
+  GSList *clist = NULL;
+
+  if (!entry)
+    return NULL;
+  for (i = 0; i < n; i++)
+    {
+      g_closure_remove_invalidate_notifier (entry[i].closure, accel_group, accel_tag_func);
+      clist = g_slist_prepend (clist, entry[i].closure);
+    }
+
+  accel_group->n_accels -= n;
+  g_memmove (entry, entry + n,
+            (accel_group->n_accels - pos) * sizeof (accel_group->priv_accels[0]));
+
+  return clist;
 }
 
 /**
- * gtk_accel_group_add:
- * @accel_group: a #GtkAccelGroup
- * @accel_key: accelerator keyval
- * @accel_mods: accelerator modifiers
- * @accel_flags: accelerator flags
- * @object: object that @accel_signal will be emitted on
- * @accel_signal: name of a #G_SIGNAL_ACTION signal to emit
- *
- * Adds an accelerator to @accel_group. When the accelerator is
- * activated, the @accel_signal signal will be emitted on @object.
- *
- * So for example, to click a button when Ctrl+a is pressed, you would
- * write: gtk_accel_group_add (accel_group, GDK_a, GDK_CONTROL_MASK,
- * 0, G_OBJECT (button), "clicked").
+ * gtk_accel_group_connect
+ * @accel_group:      the ccelerator group to install an accelerator in
+ * @accel_key:        key value of the accelerator
+ * @accel_mods:       modifier combination of the accelerator
+ * @accel_flags:      a flag mask to configure this accelerator
+ * @closure:          closure to be executed upon accelerator activation
+ * @accel_path_quark: accelerator path quark from GtkAccelMapNotify
  *
- * @accel_flags is not particularly useful, always pass 0 for
- * normal applications.
- *
- * @object must be an object that specifically supports accelerators,
- * such as #GtkWidget.
- **/
+ * Install an accelerator in this group. When @accel_group is being activated
+ * in response to a call to gtk_accel_groups_activate(), @closure will be
+ * invoked if the @accel_key and @accel_mods from gtk_accel_groups_activate()
+ * match those of this connection.
+ * The signature used for the @closure is that of #GtkAccelGroupActivate.
+ * If this connection is made in response to an accelerator path change (see
+ * gtk_accel_map_change_entry()) from a #GtkAccelMapNotify notifier,
+ * @accel_path_quark must be passed on from the notifier into this function,
+ * it should be 0 otherwise.
+ */
 void
-gtk_accel_group_add (GtkAccelGroup     *accel_group,
-                    guint               accel_key,
-                    GdkModifierType     accel_mods,
-                    GtkAccelFlags       accel_flags,
-                    GObject            *object,
-                    const gchar        *accel_signal)
+gtk_accel_group_connect (GtkAccelGroup *accel_group,
+                        guint           accel_key,
+                        GdkModifierType accel_mods,
+                        GtkAccelFlags   accel_flags,
+                        GClosure       *closure,
+                        GQuark          accel_path_quark)
 {
-  guint accel_signal_id = 0;
-  guint add_accelerator_signal_id = 0;
-  guint remove_accelerator_signal_id = 0;
-  gchar *signal;
-  GSignalQuery query;
-  GSList *slist;
-  GSList *groups;
-  GSList *attach_objects;
-  GtkAccelEntry *entry;
-  
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-  g_return_if_fail (G_IS_OBJECT (object));
-  g_return_if_fail (accel_signal != NULL);
-  
-  /* check for required signals in the objects branch
-   */
-  signal = (gchar*) accel_signal;
-  accel_signal_id = g_signal_lookup (signal, G_OBJECT_TYPE (object));
-  if (accel_signal_id)
-    {
-      signal = "add-accelerator";
-      add_accelerator_signal_id = g_signal_lookup (signal, G_OBJECT_TYPE (object));
-    }
-  if (add_accelerator_signal_id)
-    {
-      signal = "remove-accelerator";
-      remove_accelerator_signal_id = g_signal_lookup (signal, G_OBJECT_TYPE (object));
-    }
-  if (!accel_signal_id ||
-      !add_accelerator_signal_id ||
-      !remove_accelerator_signal_id)
-    {
-      g_warning ("gtk_accel_group_add(): could not find signal \"%s\""
-                "in the `%s' class ancestry",
-                signal,
-                g_type_name (G_OBJECT_TYPE (object)));
-      return;
-    }
-  g_signal_query (accel_signal_id, &query);
-  if (!query.signal_id || query.n_params > 0)
-    {
-      g_warning ("gtk_accel_group_add(): signal \"%s\" in the `%s' class ancestry"
-                "cannot be used as accelerator signal %s",
-                accel_signal,
-                g_type_name (G_OBJECT_TYPE (object)),
-                query.n_params > 0 ? "(extraneous parameters are not supported)" : "");
-      return;
-    }
+  gchar *accel_name;
+  GQuark accel_quark;
+
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+  g_return_if_fail (closure != NULL);
+  g_return_if_fail (accel_key > 0);
+
+  accel_name = gtk_accelerator_name (accel_key, accel_mods);
+  accel_quark = g_quark_from_string (accel_name);
+  g_free (accel_name);
+
+  quick_accel_add (accel_group, accel_key, accel_mods, accel_flags, closure, accel_path_quark);
+
+  /* setup handler */
+  g_signal_connect_closure_by_id (accel_group, signal_accel_activate, accel_quark, closure, FALSE);
+
+  /* and notify */
+  g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure);
+}
+
+static gboolean
+accel_group_disconnect_closure (GtkAccelGroup  *accel_group,
+                               guint           accel_key,
+                               GdkModifierType accel_mods,
+                               GClosure       *closure)
+{
+  gchar *accel_name;
+  GQuark accel_quark;
+  GSList *clist , *slist;
+  gboolean removed_some = FALSE;
+
+  accel_name = gtk_accelerator_name (accel_key, accel_mods);
+  accel_quark = g_quark_from_string (accel_name);
+  g_free (accel_name);
+
+  clist = quick_accel_remove (accel_group, accel_key, accel_mods);
+  if (!clist)
+    return FALSE;
 
-  /* prematurely abort if the group/entry is already locked
-   */
-  if (accel_group->lock_count > 0)
-    return;
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (entry && entry->accel_flags & GTK_ACCEL_LOCKED)
-    return;
-  
-  /* make sure our structures stay alive
-   */
   g_object_ref (accel_group);
-  g_object_ref (object);
-  
-  /* remove an existing entry
-   */
-  if (entry)
-    g_signal_emit (entry->object, remove_accelerator_signal_id, 0,
-                  accel_group,
-                  gdk_keyval_to_lower (accel_key),
-                  accel_mods & accel_group->modifier_mask);
-  
-  /* abort if the entry still exists
-   */
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (entry)
-    {
-      g_object_unref (accel_group);
-      g_object_unref (object);
-      
-      return;
-    }
-  
-  /* collect accel groups and remove existing entries
-   */
-  attach_objects = accel_group->attach_objects;
-  groups = NULL;
-  for (attach_objects = accel_group->attach_objects; attach_objects; attach_objects = attach_objects->next)
-    {
-      GSList *tmp_groups;
-      
-      tmp_groups = g_object_get_qdata (attach_objects->data, accel_groups_key_id);
-      while (tmp_groups)
-       {
-         groups = g_slist_prepend (groups, tmp_groups->data);
-         g_object_ref (tmp_groups->data);
-         tmp_groups = tmp_groups->next;
-       }
-    }
-  for (slist = groups; slist; slist = slist->next)
-    {
-      GtkAccelGroup *tmp_group;
-      
-      tmp_group = slist->data;
-      
-      /* we only remove the accelerator if neccessary
-       */
-      if (tmp_group->lock_count == 0)
-       {
-         entry = gtk_accel_group_lookup (tmp_group, accel_key, accel_mods);
-         if (entry && !(entry->accel_flags & GTK_ACCEL_LOCKED))
-           g_signal_emit (entry->object, remove_accelerator_signal_id, 0,
-                          tmp_group,
-                          gdk_keyval_to_lower (accel_key),
-                          accel_mods & tmp_group->modifier_mask);
-       }
-      g_object_unref (tmp_group);
-    }
-  g_slist_free (groups);
-  
-  /* now install the new accelerator
-   */
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (!entry)
-    g_signal_emit (object, add_accelerator_signal_id, 0,
-                  accel_signal_id,
-                  accel_group,
-                  gdk_keyval_to_lower (accel_key),
-                  accel_mods & accel_group->modifier_mask,
-                  accel_flags & GTK_ACCEL_MASK);
-  
-  /* and release the structures again
-   */
+
+  for (slist = clist; slist; slist = slist->next)
+    if (!closure || slist->data == (gpointer) closure)
+      {
+       g_signal_handlers_disconnect_matched (accel_group, G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_ID,
+                                             signal_accel_activate, 0,
+                                             slist->data, NULL, NULL);
+       /* and notify */
+       g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, slist->data);
+       
+       /* remove quick_accel_add() ref_count */
+       g_closure_unref (slist->data);
+
+       removed_some = TRUE;
+      }
+  g_slist_free (clist);
+
   g_object_unref (accel_group);
-  g_object_unref (object);
+  
+  return removed_some;
 }
 
-static void
-gtk_accel_group_delete_entries (GSList *entries)
+/**
+ * gtk_accel_group_disconnect
+ * @accel_group:      the ccelerator group to install an accelerator in
+ * @accel_key:        key value of the accelerator
+ * @accel_mods:       modifier combination of the accelerator
+ * @returns:          %TRUE if there was an accelerator which could be removed, %FALSE otherwise
+ *
+ * Remove an accelerator previously installed through
+ * gtk_accel_group_connect().
+ */
+gboolean
+gtk_accel_group_disconnect (GtkAccelGroup  *accel_group,
+                           guint           accel_key,
+                           GdkModifierType accel_mods)
 {
-  GSList *slist;
-  
-  /* we remove all entries of this object the hard
-   * way (i.e. without signal emission).
-   */
-  for (slist = entries; slist; slist = slist->next)
-    {
-      GtkAccelEntry *entry;
-      
-      entry = slist->data;
-      
-      g_hash_table_remove (accel_entry_hash_table, entry);
-      g_object_unref (entry->accel_group);
-      g_chunk_free (entry, accel_entries_mem_chunk);
-    }
-  g_slist_free (entries);
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+  return accel_group_disconnect_closure (accel_group, accel_key, accel_mods, NULL);
 }
 
-void
-gtk_accel_group_handle_add (GObject          *object,
-                           guint              accel_signal_id,
-                           GtkAccelGroup     *accel_group,
-                           guint              accel_key,
-                           GdkModifierType    accel_mods,
-                           GtkAccelFlags      accel_flags)
+GtkAccelGroupEntry*
+gtk_accel_group_query (GtkAccelGroup  *accel_group,
+                      guint           accel_key,
+                      GdkModifierType accel_mods,
+                      guint          *n_entries)
 {
-  GtkAccelEntry *entry;
-  
-  g_return_if_fail (G_IS_OBJECT (object));
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-  g_return_if_fail (accel_signal_id > 0);
+  GtkAccelGroupEntry *entries;
+  guint n;
 
-  if (!gtk_accelerator_valid (accel_key, accel_mods))
-    return;
-  
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (!entry)
-    {
-      GSList *slist;
-      
-      g_object_ref (accel_group);
-      
-      entry = g_chunk_new (GtkAccelEntry, accel_entries_mem_chunk);
-      entry->accel_group = accel_group;
-      entry->accelerator_key = gdk_keyval_to_lower (accel_key);
-      entry->accelerator_mods = accel_mods & accel_group->modifier_mask;
-      entry->accel_flags = accel_flags & GTK_ACCEL_MASK;
-      entry->object = object;
-      entry->signal_id = accel_signal_id;
-      
-      g_hash_table_insert (accel_entry_hash_table, entry, entry);
-      
-      slist = g_object_steal_qdata (object, accel_entries_key_id);
-      slist = g_slist_prepend (slist, entry);
-      g_object_set_qdata_full (object, accel_entries_key_id, slist,
-                              (GDestroyNotify) gtk_accel_group_delete_entries);
-    }
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+
+  entries = quick_accel_find (accel_group, accel_key, accel_mods, &n);
+
+  if (n_entries)
+    *n_entries = entries ? n : 0;
+
+  return entries;
 }
 
-/**
- * gtk_accel_group_remove:
- * @accel_group: a #GtkAccelGroup
- * @accel_key: accelerator keyval
- * @accel_mods: accelerator modifiers
- * @object: object the accelerator activates
- *
- * Removes an accelerator. The @accel_key, @accel_mods, and @object
- * arguments are the same ones used to add the accelerator
- * with gtk_accel_group_add().
- * 
- **/
-void
-gtk_accel_group_remove (GtkAccelGroup    *accel_group,
-                       guint              accel_key,
-                       GdkModifierType    accel_mods,
-                       GObject           *object)
+static gboolean
+find_accel_closure (GtkAccelKey *key,
+                   GClosure    *closure,
+                   gpointer     data)
 {
-  GtkAccelEntry *entry;
-  guint remove_accelerator_signal_id = 0;
-  
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-  g_return_if_fail (G_IS_OBJECT (object));
-  
-  /* check for required signals in the objects branch
-   */
-  remove_accelerator_signal_id = g_signal_lookup ("remove-accelerator", G_OBJECT_TYPE (object));
-  if (!remove_accelerator_signal_id)
-    {
-      g_warning ("gtk_accel_group_remove(): could not find signal \"%s\""
-                "in the `%s' class ancestry",
-                "remove-accelerator",
-                g_type_name (G_OBJECT_TYPE (object)));
-      return;
-    }
-  
-  /* prematurely abort if the entry is locked
-   */
-  if (accel_group->lock_count > 0)
-    return;
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (!entry ||
-      entry->accel_flags & GTK_ACCEL_LOCKED)
-    return;
-  if (entry->object != object)
-    {
-      g_warning ("gtk_accel_group_remove(): invalid object reference for accel-group entry");
-      return;
-    }
-  
-  /* make sure our structures stay alive
-   */
-  g_object_ref (accel_group);
-  g_object_ref (object);
-  
-  /* remove the entry
-   */
-  g_signal_emit (entry->object, remove_accelerator_signal_id, 0,
-                accel_group,
-                gdk_keyval_to_lower (accel_key),
-                accel_mods & accel_group->modifier_mask);
-  
-  /* and release the structures again
-   */
-  g_object_unref (accel_group);
-  g_object_unref (object);
+  return data == (gpointer) closure;
 }
 
-void
-gtk_accel_group_handle_remove (GObject          *object,
-                              GtkAccelGroup     *accel_group,
-                              guint              accel_key,
-                              GdkModifierType    accel_mods)
+gboolean
+gtk_accel_groups_disconnect_closure (GClosure *closure)
 {
-  GtkAccelEntry *entry;
-  
-  g_return_if_fail (G_IS_OBJECT (object));
-  g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-  
-  entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
-  if (entry)
+  GtkAccelGroup *group;
+
+  g_return_val_if_fail (closure != NULL, FALSE);
+
+  group = gtk_accel_group_from_accel_closure (closure);
+  if (group)
     {
-      if (entry->object == object)
+      GtkAccelKey *key = gtk_accel_group_find (group, find_accel_closure, closure);
+
+      /* sigh, not finding the key can unexpectedly happen if someone disposes
+       * accel groups. that's highly recommended to _not_ do though.
+       */
+      if (key)
        {
-         GSList *slist;
-         
-         g_hash_table_remove (accel_entry_hash_table, entry);
-         
-         slist = g_object_steal_qdata (object, accel_entries_key_id);
-         if (slist)
-           {
-             slist = g_slist_remove (slist, entry);
-             if (slist)
-               g_object_set_qdata_full (object, accel_entries_key_id, slist,
-                                        (GDestroyNotify) gtk_accel_group_delete_entries);
-             
-             g_object_unref (accel_group);
-             
-             g_chunk_free (entry, accel_entries_mem_chunk);
-           }
+         accel_group_disconnect_closure (group, key->accel_key, key->accel_mods, closure);
+         return TRUE;
        }
-      else
-       g_warning ("gtk_accel_group_handle_remove(): invalid object reference for accel-group entry");
     }
-  else
-    g_warning ("gtk_accel_group_handle_remove(): attempt to remove unexisting accel-group entry");
+  return FALSE;
 }
 
-guint
-gtk_accel_group_create_add (GType        class_type,
-                           GSignalFlags signal_flags,
-                           guint        handler_offset)
+GtkAccelGroup*
+gtk_accel_group_from_accel_closure (GClosure *closure)
 {
-  g_return_val_if_fail (G_TYPE_IS_OBJECT (class_type), 0);
-
-  return g_signal_new ("add-accelerator",
-                      class_type,
-                      signal_flags,
-                      handler_offset,
-                      (GSignalAccumulator) NULL, NULL,
-                      gtk_marshal_VOID__UINT_OBJECT_UINT_FLAGS_FLAGS,
-                      G_TYPE_NONE, 5,
-                      G_TYPE_UINT,
-                      GTK_TYPE_ACCEL_GROUP,
-                      G_TYPE_UINT,
-                      GDK_TYPE_MODIFIER_TYPE,
-                      GTK_TYPE_ACCEL_FLAGS);
+  guint i;
+
+  g_return_val_if_fail (closure != NULL, NULL);
+
+  /* a few remarks on wat we do here. in general, we need a way to back-lookup
+   * accel_groups from closures that are being used in accel groups. this could
+   * be done e.g via a hashtable. it is however cheaper (memory wise) to just
+   * store a NOP notifier on the closure itself that contains the accel group
+   * as data which, besides needing to peek a bit at closure internals, works
+   * just as good.
+   */
+  for (i = 0; i < G_CLOSURE_N_NOTIFIERS (closure); i++)
+    if (closure->notifiers[i].notify == accel_tag_func)
+      return closure->notifiers[i].data;
+
+  return NULL;
 }
 
-guint
-gtk_accel_group_create_remove (GType        class_type,
-                              GSignalFlags signal_flags,
-                              guint        handler_offset)
+gboolean
+_gtk_accel_group_activate (GtkAccelGroup  *accel_group,
+                          GQuark          accel_quark,
+                          GObject        *acceleratable,
+                          guint           accel_key,
+                          GdkModifierType accel_mods)
 {
-  g_return_val_if_fail (G_TYPE_IS_OBJECT (class_type), 0);
-
-  return g_signal_new ("remove-accelerator",
-                      class_type,
-                      signal_flags,
-                      handler_offset,
-                      (GSignalAccumulator) NULL, NULL,
-                      gtk_marshal_VOID__OBJECT_UINT_FLAGS,
-                      G_TYPE_NONE, 3,
-                      GTK_TYPE_ACCEL_GROUP,
-                      G_TYPE_UINT,
-                      GDK_TYPE_MODIFIER_TYPE);
+  gboolean was_handled;
+
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+  was_handled = FALSE;
+  g_signal_emit (accel_group, signal_accel_activate, accel_quark,
+                acceleratable, accel_key, accel_mods, &was_handled);
+
+  return was_handled;
 }
 
-GSList*
-gtk_accel_groups_from_object (GObject       *object)
+/**
+ * gtk_accel_groups_activate:
+ * @acceleratable: usually a #GtkWindow
+ * @accel_key:     accelerator keyval from a key event
+ * @accel_mods:    keyboard state mask from a key event
+ * @returns:       %TRUE if the accelerator was handled, %FALSE otherwise
+ * 
+ * Finds the first accelerator in any #GtkAccelGroup attached
+ * to @acceleratable that matches @accel_key and @accel_mods, and
+ * activates that accelerator.
+ * If an accelerator was activated and handled this keypress, %TRUE
+ * is returned.
+ */
+gboolean
+gtk_accel_groups_activate (GObject       *acceleratable,
+                          guint           accel_key,
+                          GdkModifierType accel_mods)
 {
-  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+  g_return_val_if_fail (G_IS_OBJECT (acceleratable), FALSE);
   
-  return g_object_get_qdata (object, accel_groups_key_id);
-}
+  if (gtk_accelerator_valid (accel_key, accel_mods))
+    {
+      gchar *accel_name;
+      GQuark accel_quark;
+      GSList *slist;
 
-GSList*
-gtk_accel_group_entries_from_object (GObject        *object)
-{
-  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+      accel_name = gtk_accelerator_name (accel_key, accel_mods);
+      accel_quark = g_quark_from_string (accel_name);
+      g_free (accel_name);
+      
+      for (slist = gtk_accel_groups_from_acceleratable (acceleratable); slist; slist = slist->next)
+       if (_gtk_accel_group_activate (slist->data, accel_quark, acceleratable, accel_key, accel_mods))
+         return TRUE;
+    }
   
-  return g_object_get_qdata (object, accel_entries_key_id);
+  return FALSE;
 }
 
 /**
- * gtk_accelerator_valid:
- * @keyval: a GDK keyval
+ * gtk_accelerator_valid
+ * @keyval:    a GDK keyval
  * @modifiers: modifier mask
+ * @returns:   %TRUE if the accelerator is valid
  * 
  * Determines whether a given keyval and modifier mask constitute
  * a valid keyboard accelerator. For example, the GDK_a keyval
  * plus GDK_CONTROL_MASK is valid - this is a "Ctrl+a" accelerator.
- * But you can't use the NumLock key as an accelerator.
- * 
- * Return value: %TRUE if the accelerator is valid
- **/
+ * But by default (see gtk_accelerator_set_default_mod_mask()) you
+ * cannot use the NumLock key as an accelerator modifier.
+ */
 gboolean
 gtk_accelerator_valid (guint             keyval,
                       GdkModifierType    modifiers)
@@ -1018,10 +784,10 @@ is_release (const gchar *string)
 }
 
 /**
- * gtk_accelerator_parse:
- * @accelerator: string representing an accelerator
- * @accelerator_key: return location for accelerator keyval
- * @accelerator_mods: return location for accelerator mod mask
+ * gtk_accelerator_parse
+ * @accelerator:      string representing an accelerator
+ * @accelerator_key:  return location for accelerator keyval
+ * @accelerator_mods: return location for accelerator modifier mask
  *
  * Parses a string representing an accelerator. The
  * format looks like "<Control>a" or "<Shift><Alt>F1" or
@@ -1031,11 +797,11 @@ is_release (const gchar *string)
  *
  * If the parse fails, @accelerator_key and @accelerator_mods will
  * be set to 0 (zero).
- **/
+ */
 void
-gtk_accelerator_parse (const gchar    *accelerator,
-                      guint          *accelerator_key,
-                      GdkModifierType*accelerator_mods)
+gtk_accelerator_parse (const gchar     *accelerator,
+                      guint           *accelerator_key,
+                      GdkModifierType *accelerator_mods)
 {
   guint keyval;
   GdkModifierType mods;
@@ -1136,19 +902,18 @@ gtk_accelerator_parse (const gchar    *accelerator,
 }
 
 /**
- * gtk_accelerator_name:
- * @accelerator_key: an accelerator keyval
- * @accelerator_mods: modifier mask
+ * gtk_accelerator_name
+ * @accelerator_key:  accelerator keyval
+ * @accelerator_mods: accelerator modifier mask
+ * @returns:          a newly allocated accelerator name
  * 
  * Converts an accelerator keyval and modifier mask
  * into a string parseable by gtk_accelerator_parse().
  * For example, if you pass in GDK_q and GDK_CONTROL_MASK,
  * this function returns "<Control>q". 
  *
- * The caller of this function must free the return value.
- * 
- * Return value: the new accelerator name
- **/
+ * The caller of this function must free the returned string.
+ */
 gchar*
 gtk_accelerator_name (guint           accelerator_key,
                      GdkModifierType accelerator_mods)
@@ -1240,18 +1005,17 @@ gtk_accelerator_name (guint           accelerator_key,
 }
 
 /**
- * gtk_accelerator_set_default_mod_mask:
- * @default_mod_mask: a modifier mask
+ * gtk_accelerator_set_default_mod_mask
+ * @default_mod_mask: accelerator modifier mask
  *
  * Sets the modifiers that will be considered significant for keyboard
  * accelerators. The default mod mask is #GDK_CONTROL_MASK |
  * #GDK_SHIFT_MASK | #GDK_MOD1_MASK, that is, Control, Shift, and Alt.
- * Other modifiers will be ignored by #GtkAccelGroup.
+ * Other modifiers will by default be ignored by #GtkAccelGroup.
  *
  * The default mod mask should be changed on application startup,
- * before creating any accelerator groups.
- * 
- **/
+ * before using any accelerator groups.
+ */
 void
 gtk_accelerator_set_default_mod_mask (GdkModifierType default_mod_mask)
 {
@@ -1259,12 +1023,11 @@ gtk_accelerator_set_default_mod_mask (GdkModifierType default_mod_mask)
 }
 
 /**
- * gtk_accelerator_get_default_mod_mask:
+ * gtk_accelerator_get_default_mod_mask
+ * @returns: the default accelerator modifier mask
  *
  * Gets the value set by gtk_accelerator_set_default_mod_mask().
- * 
- * Return value: the default modifier mask.
- **/
+ */
 guint
 gtk_accelerator_get_default_mod_mask (void)
 {
index d3e8d1fb481d373a894f69bbf27c3a75564b9ae7..5fca1a33b3547f3b22f59fef293b4c2f3561ed02 100644 (file)
@@ -1,8 +1,5 @@
 /* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GtkAccelGroup: Accelerator manager for GtkObjects.
- * Copyright (C) 1998 Tim Janik
+ * Copyright (C) 1998, 2001 Tim Janik
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 
 
 #include <gdk/gdk.h>
-#include <gtk/gtkobject.h>
 #include <gtk/gtkenums.h>
 
-
 G_BEGIN_DECLS
 
 
+/* --- type macros --- */
 #define GTK_TYPE_ACCEL_GROUP              (gtk_accel_group_get_type ())
 #define GTK_ACCEL_GROUP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_ACCEL_GROUP, GtkAccelGroup))
 #define GTK_ACCEL_GROUP_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupClass))
@@ -47,136 +43,113 @@ G_BEGIN_DECLS
 #define GTK_ACCEL_GROUP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupClass))
 
 
-typedef struct _GtkAccelGroup     GtkAccelGroup;
-typedef struct _GtkAccelGroupClass GtkAccelGroupClass;
-typedef struct _GtkAccelEntry     GtkAccelEntry;
-
+/* --- accel flags --- */
 typedef enum
 {
-  /* should the accelerator appear in
-   * the widget's display?
-   */
-  GTK_ACCEL_VISIBLE        = 1 << 0,
-  /* should the signal associated with
-   * this accelerator be also visible?
-   */
-  GTK_ACCEL_SIGNAL_VISIBLE = 1 << 1,
-  /* may the accelerator be removed
-   * again?
-   */
-  GTK_ACCEL_LOCKED         = 1 << 2,
+  GTK_ACCEL_VISIBLE        = 1 << 0,   /* display in GtkAccelLabel? */
+  GTK_ACCEL_LOCKED         = 1 << 1,   /* is it removable? */
   GTK_ACCEL_MASK           = 0x07
 } GtkAccelFlags;
 
+
+/* --- typedefs & structures --- */
+typedef struct _GtkAccelGroup     GtkAccelGroup;
+typedef struct _GtkAccelGroupClass GtkAccelGroupClass;
+typedef struct _GtkAccelKey        GtkAccelKey;
+typedef struct _GtkAccelGroupEntry GtkAccelGroupEntry;
+typedef gboolean (*GtkAccelGroupActivate) (GtkAccelGroup  *accel_group,
+                                          GObject        *acceleratable,
+                                          guint           keyval,
+                                          GdkModifierType modifier);
 struct _GtkAccelGroup
 {
-  GObject         parent;
-  guint                  lock_count;
-  GdkModifierType modifier_mask;
-  GSList         *attach_objects;
+  GObject             parent;
+  guint                      lock_count;
+  GdkModifierType     modifier_mask;
+  GSList             *acceleratables;
+  guint                      n_accels;
+  GtkAccelGroupEntry *priv_accels;
 };
-
 struct _GtkAccelGroupClass
 {
   GObjectClass parent_class;
-};
 
-struct _GtkAccelEntry
+  void (*accel_changed)        (GtkAccelGroup  *accel_group,
+                                guint           keyval,
+                                GdkModifierType modifier,
+                                GClosure       *accel_closure);
+};
+struct _GtkAccelKey
 {
-  /* key portion
-   */
-  GtkAccelGroup                *accel_group;
-  guint                         accelerator_key;
-  GdkModifierType       accelerator_mods;
-  
-  GtkAccelFlags                 accel_flags;
-  GObject              *object;
-  guint                         signal_id;
+  guint           accel_key;
+  GdkModifierType accel_mods;
+  guint           accel_flags : 16;
 };
 
 
-/* Accelerators
- */
-gboolean gtk_accelerator_valid               (guint            keyval,
-                                              GdkModifierType  modifiers) G_GNUC_CONST;
-void    gtk_accelerator_parse                (const gchar     *accelerator,
-                                              guint           *accelerator_key,
-                                              GdkModifierType *accelerator_mods);
-gchar*  gtk_accelerator_name                 (guint            accelerator_key,
-                                              GdkModifierType  accelerator_mods);
-void    gtk_accelerator_set_default_mod_mask (GdkModifierType  default_mod_mask);
-guint   gtk_accelerator_get_default_mod_mask (void);
-
-
-/* Accelerator Groups
- */
+/* -- Accelerator Groups --- */
 GType           gtk_accel_group_get_type        (void);
 GtkAccelGroup*  gtk_accel_group_new            (void);
-GtkAccelGroup*  gtk_accel_group_get_default            (void);
-GtkAccelGroup*  gtk_accel_group_ref            (GtkAccelGroup  *accel_group);
-void           gtk_accel_group_unref           (GtkAccelGroup  *accel_group);
 void           gtk_accel_group_lock            (GtkAccelGroup  *accel_group);
 void           gtk_accel_group_unlock          (GtkAccelGroup  *accel_group);
-gboolean        gtk_accel_groups_activate              (GObject        *object,
+void           gtk_accel_group_connect         (GtkAccelGroup  *accel_group,
                                                 guint           accel_key,
-                                                GdkModifierType accel_mods);
-
-/* internal functions
- */
-gboolean        gtk_accel_group_activate       (GtkAccelGroup  *accel_group,
+                                                GdkModifierType accel_mods,
+                                                GtkAccelFlags   accel_flags,
+                                                GClosure       *closure,
+                                                GQuark          accel_path_quark);
+gboolean       gtk_accel_group_disconnect      (GtkAccelGroup  *accel_group,
                                                 guint           accel_key,
                                                 GdkModifierType accel_mods);
-void           gtk_accel_group_attach          (GtkAccelGroup  *accel_group,
+gboolean    gtk_accel_groups_disconnect_closure        (GClosure       *closure);
+
+
+/* --- GtkActivatable glue --- */
+void           _gtk_accel_group_attach         (GtkAccelGroup  *accel_group,
                                                 GObject        *object);
-void           gtk_accel_group_detach          (GtkAccelGroup  *accel_group,
+void           _gtk_accel_group_detach         (GtkAccelGroup  *accel_group,
                                                 GObject        *object);
-
-/* Accelerator Group Entries (internal)
- */
-GtkAccelEntry*         gtk_accel_group_get_entry       (GtkAccelGroup  *accel_group,
-                                                guint           accel_key,
-                                                GdkModifierType accel_mods);
-void           gtk_accel_group_lock_entry      (GtkAccelGroup  *accel_group,
-                                                guint           accel_key,
-                                                GdkModifierType accel_mods);
-void           gtk_accel_group_unlock_entry    (GtkAccelGroup  *accel_group,
+gboolean        gtk_accel_groups_activate              (GObject        *acceleratable,
                                                 guint           accel_key,
                                                 GdkModifierType accel_mods);
-void           gtk_accel_group_add             (GtkAccelGroup  *accel_group,
-                                                guint           accel_key,
-                                                GdkModifierType accel_mods,
-                                                GtkAccelFlags   accel_flags,
-                                                GObject        *object,
-                                                const gchar    *accel_signal);
-void           gtk_accel_group_remove          (GtkAccelGroup  *accel_group,
-                                                guint           accel_key,
-                                                GdkModifierType accel_mods,
-                                                GObject        *object);
+GSList*            gtk_accel_groups_from_acceleratable (GObject        *object);
+GtkAccelKey*   gtk_accel_group_find            (GtkAccelGroup  *accel_group,
+                                                gboolean (*find_func) (GtkAccelKey *key,
+                                                                       GClosure    *closure,
+                                                                       gpointer     data),
+                                                gpointer        data);
+GtkAccelGroup* gtk_accel_group_from_accel_closure (GClosure    *closure);
 
-/* Accelerator Signals (internal)
- */
-void           gtk_accel_group_handle_add      (GObject        *object,
-                                                guint           accel_signal_id,
-                                                GtkAccelGroup  *accel_group,
+
+/* --- Accelerators--- */
+gboolean gtk_accelerator_valid               (guint            keyval,
+                                              GdkModifierType  modifiers) G_GNUC_CONST;
+void    gtk_accelerator_parse                (const gchar     *accelerator,
+                                              guint           *accelerator_key,
+                                              GdkModifierType *accelerator_mods);
+gchar*  gtk_accelerator_name                 (guint            accelerator_key,
+                                              GdkModifierType  accelerator_mods);
+void    gtk_accelerator_set_default_mod_mask (GdkModifierType  default_mod_mask);
+guint   gtk_accelerator_get_default_mod_mask (void);
+
+
+/* --- internal --- */
+GtkAccelGroupEntry*    gtk_accel_group_query   (GtkAccelGroup  *accel_group,
                                                 guint           accel_key,
                                                 GdkModifierType accel_mods,
-                                                GtkAccelFlags   accel_flags);
-void           gtk_accel_group_handle_remove   (GObject        *object,
-                                                GtkAccelGroup  *accel_group,
-                                                guint           accel_key,
-                                                GdkModifierType accel_mods);
-guint          gtk_accel_group_create_add      (GType           class_type,
-                                                GSignalFlags    signal_flags,
-                                                guint           handler_offset);
-guint          gtk_accel_group_create_remove   (GType           class_type,
-                                                GSignalFlags    signal_flags,
-                                                guint           handler_offset);
-
-/* Miscellaneous (internal)
- */
-GSList*        gtk_accel_groups_from_object            (GObject        *object);
-GSList*        gtk_accel_group_entries_from_object     (GObject        *object);
+                                                guint          *n_entries);
+struct _GtkAccelGroupEntry
+{
+  GtkAccelKey  key;
+  GClosure    *closure;
+  GQuark       accel_path_quark;
+};
+
 
+#ifndef GTK_DISABLE_DEPRECATED
+#define        gtk_accel_group_ref     g_object_ref
+#define        gtk_accel_group_unref   g_object_unref
+#endif /* GTK_DISABLE_DEPRECATED */
 
 G_END_DECLS
 
index 82b4f35bebfcaeadb85e3029e325c648c0d3cffe..bee1060bd89b3ffcce149a8da7375158c1078798 100644 (file)
  * files for a list of changes.  These files are distributed with
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
-
-#include <string.h>
-#include <ctype.h>
+#include "gtkaccellabel.h"
+#include "gtkaccelmap.h"
 #include "gtkmain.h"
 #include "gtksignal.h"
-#include "gtkaccellabel.h"
 #include "gtkintl.h"
 
+#include <string.h>
+#include <ctype.h>
+
 enum {
   PROP_0,
-  PROP_ACCEL_OBJECT
+  PROP_ACCEL_CLOSURE,
+  PROP_ACCEL_WIDGET
 };
 
 static void     gtk_accel_label_class_init   (GtkAccelLabelClass *klass);
@@ -90,33 +92,17 @@ static void
 gtk_accel_label_class_init (GtkAccelLabelClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-  GtkObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-  GtkMiscClass *misc_class;
-  GtkLabelClass *label_class;
+  GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   
   accel_label_class = class;
-  object_class = (GtkObjectClass*) class;
-  widget_class = (GtkWidgetClass*) class;
-  misc_class = (GtkMiscClass*) class;
-  label_class = (GtkLabelClass*) class;
-  
-  parent_class = gtk_type_class (GTK_TYPE_LABEL);
+  parent_class = g_type_class_peek_parent (class);
   
   gobject_class->finalize = gtk_accel_label_finalize;
   gobject_class->set_property = gtk_accel_label_set_property;
   gobject_class->get_property = gtk_accel_label_get_property;
   
   object_class->destroy = gtk_accel_label_destroy;
-  
-  g_object_class_install_property (G_OBJECT_CLASS(object_class),
-                                   PROP_ACCEL_OBJECT,
-                                   g_param_spec_object ("accel_object",
-                                                        _("Accelerator object"),
-                                                        _("The object monitored by this accelerator label"),
-                                                        G_TYPE_OBJECT,
-                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
-
    
   widget_class->size_request = gtk_accel_label_size_request;
   widget_class->expose_event = gtk_accel_label_expose_event;
@@ -129,6 +115,21 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
   class->mod_separator = g_strdup ("+");
   class->accel_seperator = g_strdup (" / ");
   class->latin1_to_char = TRUE;
+  
+  g_object_class_install_property (G_OBJECT_CLASS (object_class),
+                                   PROP_ACCEL_CLOSURE,
+                                   g_param_spec_object ("accel_closure",
+                                                        _("Accelerator Closure"),
+                                                        _("The closure to be monitored for accelerator changes"),
+                                                        GTK_TYPE_WIDGET,
+                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (object_class),
+                                   PROP_ACCEL_WIDGET,
+                                   g_param_spec_object ("accel_widget",
+                                                        _("Accelerator Widget"),
+                                                        _("The widget to be monitored for accelerator changes"),
+                                                        GTK_TYPE_WIDGET,
+                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
 }
 
 static void
@@ -143,8 +144,11 @@ gtk_accel_label_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_ACCEL_OBJECT:
-      gtk_accel_label_set_accel_object (accel_label, g_value_get_object (value));
+    case PROP_ACCEL_CLOSURE:
+      gtk_accel_label_set_accel_closure (accel_label, g_value_get_boxed (value));
+      break;
+    case PROP_ACCEL_WIDGET:
+      gtk_accel_label_set_accel_widget (accel_label, g_value_get_object (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -152,10 +156,11 @@ gtk_accel_label_set_property (GObject      *object,
     }
 }
 
-static void gtk_accel_label_get_property (GObject    *object,
-                                         guint       prop_id,
-                                         GValue     *value,
-                                         GParamSpec *pspec)
+static void
+gtk_accel_label_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
 {
   GtkAccelLabel  *accel_label;
 
@@ -163,8 +168,11 @@ static void gtk_accel_label_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_ACCEL_OBJECT:
-       g_value_set_object (value, accel_label->accel_object);
+    case PROP_ACCEL_CLOSURE:
+      g_value_set_boxed (value, accel_label->accel_closure);
+      break;
+    case PROP_ACCEL_WIDGET:
+      g_value_set_object (value, accel_label->accel_widget);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -177,7 +185,9 @@ gtk_accel_label_init (GtkAccelLabel *accel_label)
 {
   accel_label->queue_id = 0;
   accel_label->accel_padding = 3;
-  accel_label->accel_object = NULL;
+  accel_label->accel_widget = NULL;
+  accel_label->accel_closure = NULL;
+  accel_label->accel_group = NULL;
   accel_label->accel_string = NULL;
   
   gtk_accel_label_refetch (accel_label);
@@ -206,7 +216,8 @@ gtk_accel_label_destroy (GtkObject *object)
   
   accel_label = GTK_ACCEL_LABEL (object);
 
-  gtk_accel_label_set_accel_object (accel_label, NULL);
+  gtk_accel_label_set_accel_widget (accel_label, NULL);
+  gtk_accel_label_set_accel_closure (accel_label, NULL);
   
   GTK_OBJECT_CLASS (parent_class)->destroy (object);
 }
@@ -214,33 +225,34 @@ gtk_accel_label_destroy (GtkObject *object)
 static void
 gtk_accel_label_finalize (GObject *object)
 {
-  GtkAccelLabel *accel_label;
-  
-  g_return_if_fail (GTK_IS_ACCEL_LABEL (object));
-  
-  accel_label = GTK_ACCEL_LABEL (object);
-  
+  GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object);
+
+  if (accel_label->queue_id)
+    {
+      gtk_idle_remove (accel_label->queue_id);
+      accel_label->queue_id = 0;
+    }
   g_free (accel_label->accel_string);
   
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 /**
- * gtk_accel_label_get_accel_object:
+ * gtk_accel_label_get_accel_widget:
  * @accel_label: a #GtkAccelLabel
  *
  * Fetches the widget monitored by this accelerator label. See
- * gtk_accel_label_set_accel_object().
+ * gtk_accel_label_set_accel_widget().
  *
  * Return value: the object monitored by the accelerator label,
  *               or %NULL.
  **/
-GObject *
-gtk_accel_label_get_accel_object (GtkAccelLabel *accel_label)
+GtkWidget*
+gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label)
 {
   g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), NULL);
 
-  return accel_label->accel_object;
+  return accel_label->accel_widget;
 }
 
 guint
@@ -336,6 +348,55 @@ gtk_accel_label_expose_event (GtkWidget      *widget,
   return TRUE;
 }
 
+static void
+refetch_widget_accel_closure (GtkAccelLabel *accel_label)
+{
+  GSList *slist;
+
+  g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+  g_return_if_fail (GTK_IS_WIDGET (accel_label->accel_widget));
+  
+  for (slist = _gtk_widget_get_accel_closures (accel_label->accel_widget); slist; slist = slist->next)
+    if (gtk_accel_group_from_accel_closure (slist->data))
+      {
+       /* we just take the first correctly used closure */
+       gtk_accel_label_set_accel_closure (accel_label, slist->data);
+       return;
+      }
+  gtk_accel_label_set_accel_closure (accel_label, NULL);
+}
+
+void
+gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
+                                 GtkWidget     *accel_widget)
+{
+  g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+  if (accel_widget)
+    g_return_if_fail (GTK_IS_WIDGET (accel_widget));
+    
+  if (accel_widget != accel_label->accel_widget)
+    {
+      if (accel_label->accel_widget)
+       {
+         gtk_accel_label_set_accel_closure (accel_label, NULL);
+         g_signal_handlers_disconnect_by_func (accel_label->accel_widget,
+                                               G_CALLBACK (refetch_widget_accel_closure),
+                                               accel_label);
+         g_object_unref (accel_label->accel_widget);
+       }
+      accel_label->accel_widget = accel_widget;
+      if (accel_label->accel_widget)
+       {
+         g_object_ref (accel_label->accel_widget);
+         g_signal_connect_object (accel_label->accel_widget, "accel_closures_changed",
+                                  G_CALLBACK (refetch_widget_accel_closure),
+                                  accel_label, G_CONNECT_SWAPPED);
+         refetch_widget_accel_closure (accel_label);
+       }
+      g_object_notify (G_OBJECT (accel_label), "accel_widget");
+    }
+}
+
 static void
 gtk_accel_label_queue_refetch (GtkAccelLabel *accel_label)
 {
@@ -347,45 +408,46 @@ gtk_accel_label_queue_refetch (GtkAccelLabel *accel_label)
                                                   accel_label);
 }
 
+static void
+check_accel_changed (GtkAccelGroup  *accel_group,
+                    guint           keyval,
+                    GdkModifierType modifier,
+                    GClosure       *accel_closure,
+                    GtkAccelLabel  *accel_label)
+{
+  if (accel_closure == accel_label->accel_closure)
+    gtk_accel_label_queue_refetch (accel_label);
+}
+
 void
-gtk_accel_label_set_accel_object (GtkAccelLabel *accel_label,
-                                 GObject       *accel_object)
+gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
+                                  GClosure      *accel_closure)
 {
   g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
-  g_return_if_fail (accel_object == NULL || G_IS_OBJECT (accel_object));
-    
-  if (accel_object != accel_label->accel_object)
+  if (accel_closure)
+    g_return_if_fail (gtk_accel_group_from_accel_closure (accel_closure) != NULL);
+
+  if (accel_closure != accel_label->accel_closure)
     {
-      if (accel_label->accel_object)
+      if (accel_label->accel_closure)
        {
-         g_signal_handlers_disconnect_by_func (accel_label->accel_object,
-                                               G_CALLBACK (gtk_accel_label_queue_refetch),
-                                               accel_object);
-         g_object_unref (accel_label->accel_object);
+         g_signal_handlers_disconnect_by_func (accel_label->accel_group,
+                                               G_CALLBACK (check_accel_changed),
+                                               accel_label);
+         accel_label->accel_group = NULL;
+         g_closure_unref (accel_label->accel_closure);
        }
-      if (accel_label->queue_id)
+      accel_label->accel_closure = accel_closure;
+      if (accel_label->accel_closure)
        {
-         gtk_idle_remove (accel_label->queue_id);
-         accel_label->queue_id = 0;
+         g_closure_ref (accel_label->accel_closure);
+         accel_label->accel_group = gtk_accel_group_from_accel_closure (accel_closure);
+         g_signal_connect_object (accel_label->accel_group, "accel_changed",
+                                  G_CALLBACK (check_accel_changed),
+                                  accel_label, 0);
        }
-      accel_label->accel_object = accel_object;
-      if (accel_label->accel_object)
-       {
-         g_object_ref (accel_label->accel_object);
-         g_signal_connect_object (accel_label->accel_object,
-                                  "add-accelerator",
-                                  G_CALLBACK (gtk_accel_label_queue_refetch),
-                                  accel_label,
-                                  G_CONNECT_AFTER | G_CONNECT_SWAPPED);
-         g_signal_connect_object (accel_label->accel_object,
-                                  "remove-accelerator",
-                                  G_CALLBACK (gtk_accel_label_queue_refetch),
-                                  accel_label,
-                                  G_CONNECT_AFTER | G_CONNECT_SWAPPED);
-       }
-       gtk_accel_label_refetch (accel_label);
-
-       g_object_notify (G_OBJECT (accel_label), "accel_object");
+      gtk_accel_label_queue_refetch (accel_label);
+      g_object_notify (G_OBJECT (accel_label), "accel_closure");
     }
 }
 
@@ -401,107 +463,106 @@ gtk_accel_label_refetch_idle (GtkAccelLabel *accel_label)
   return retval;
 }
 
+static gboolean
+find_accel (GtkAccelKey *key,
+           GClosure    *closure,
+           gpointer     data)
+{
+  return data == (gpointer) closure;
+}
+
 gboolean
 gtk_accel_label_refetch (GtkAccelLabel *accel_label)
 {
   GtkAccelLabelClass *class;
+  gchar *utf8;
 
   g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), FALSE);
 
   class = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
-  
+
   g_free (accel_label->accel_string);
   accel_label->accel_string = NULL;
-  
-  if (accel_label->accel_object)
+
+  if (accel_label->accel_closure)
     {
-      GtkAccelEntry *entry = NULL;
-      GSList *slist;
-      
-      slist = gtk_accel_group_entries_from_object (accel_label->accel_object);
-      for (; slist; slist = slist->next)
+      GtkAccelKey *key = gtk_accel_group_find (accel_label->accel_group, find_accel, accel_label->accel_closure);
+
+      if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
        {
-         entry = slist->data;
-         if (entry->accel_flags & GTK_ACCEL_VISIBLE)
+         GString *gstring;
+         gboolean seen_mod = FALSE;
+         
+         gstring = g_string_new (accel_label->accel_string);
+         g_string_append (gstring, gstring->len ? class->accel_seperator : "   ");
+         
+         if (key->accel_mods & GDK_SHIFT_MASK)
            {
-             GString *gstring;
-             gboolean had_mod;
-             
-             gstring = g_string_new (accel_label->accel_string);
-             if (gstring->len)
-               g_string_append (gstring, class->accel_seperator);
-             else
-               g_string_append (gstring, "   ");
-
-             if (entry->accel_flags & GTK_ACCEL_SIGNAL_VISIBLE)
-               {
-                 g_string_append (gstring, class->signal_quote1);
-                 g_string_append (gstring, gtk_signal_name (entry->signal_id));
-                 g_string_append (gstring, class->signal_quote2);
-               }
-             
-             had_mod = FALSE;
-             if (entry->accelerator_mods & GDK_SHIFT_MASK)
-               {
-                 g_string_append (gstring, class->mod_name_shift);
-                 had_mod = TRUE;
-               }
-             if (entry->accelerator_mods & GDK_CONTROL_MASK)
-               {
-                 if (had_mod)
-                   g_string_append (gstring, class->mod_separator);
-                 g_string_append (gstring, class->mod_name_control);
-                 had_mod = TRUE;
-               }
-             if (entry->accelerator_mods & GDK_MOD1_MASK)
-               {
-                 if (had_mod)
-                   g_string_append (gstring, class->mod_separator);
-                 g_string_append (gstring, class->mod_name_alt);
-                 had_mod = TRUE;
-               }
-             
-             if (had_mod)
+             g_string_append (gstring, class->mod_name_shift);
+             seen_mod = TRUE;
+           }
+         if (key->accel_mods & GDK_CONTROL_MASK)
+           {
+             if (seen_mod)
                g_string_append (gstring, class->mod_separator);
-             if (entry->accelerator_key < 0x80 ||
-                 (entry->accelerator_key > 0x80 &&
-                  entry->accelerator_key <= 0xff &&
-                  class->latin1_to_char))
-               {
-                 switch (entry->accelerator_key)
-                   {
-                   case ' ':
-                     g_string_append (gstring, "Space");
-                     break;
-                   case '\\':
-                     g_string_append (gstring, "Backslash");
-                     break;
-                   default:
-                     g_string_append_c (gstring, toupper (entry->accelerator_key));
-                     break;
-                   }
-               }
-             else
+             g_string_append (gstring, class->mod_name_control);
+             seen_mod = TRUE;
+           }
+         if (key->accel_mods & GDK_MOD1_MASK)
+           {
+             if (seen_mod)
+               g_string_append (gstring, class->mod_separator);
+             g_string_append (gstring, class->mod_name_alt);
+             seen_mod = TRUE;
+           }
+         if (seen_mod)
+           g_string_append (gstring, class->mod_separator);
+         if (key->accel_key < 0x80 ||
+             (key->accel_key > 0x80 &&
+              key->accel_key <= 0xff &&
+              class->latin1_to_char))
+           {
+             switch (key->accel_key)
                {
-                 gchar *tmp;
-                 
-                 tmp = gtk_accelerator_name (entry->accelerator_key, 0);
-                 if (tmp[0] != 0 && tmp[1] == 0)
-                   tmp[0] = toupper (tmp[0]);
-                 g_string_append (gstring, tmp);
-                 g_free (tmp);
+               case ' ':
+                 g_string_append (gstring, "Space");
+                 break;
+               case '\\':
+                 g_string_append (gstring, "Backslash");
+                 break;
+               default:
+                 g_string_append_c (gstring, toupper (key->accel_key));
+                 break;
                }
-
-             g_free (accel_label->accel_string);
-             accel_label->accel_string = gstring->str;
-             g_string_free (gstring, FALSE);
            }
+         else
+           {
+             gchar *tmp;
+             
+             tmp = gtk_accelerator_name (key->accel_key, 0);
+             if (tmp[0] != 0 && tmp[1] == 0)
+               tmp[0] = toupper (tmp[0]);
+             g_string_append (gstring, tmp);
+             g_free (tmp);
+           }
+         g_free (accel_label->accel_string);
+         accel_label->accel_string = gstring->str;
+         g_string_free (gstring, FALSE);
        }
+      if (!accel_label->accel_string)
+       accel_label->accel_string = g_strdup ("-/-");
     }
-
+  
   if (!accel_label->accel_string)
     accel_label->accel_string = g_strdup ("");
 
+  utf8 = g_locale_to_utf8 (accel_label->accel_string, -1, NULL, NULL, NULL);
+  if (utf8)
+    {
+      g_free (accel_label->accel_string);
+      accel_label->accel_string = utf8;
+    }
+
   if (accel_label->queue_id)
     {
       gtk_idle_remove (accel_label->queue_id);
index 5a9b779aac59bceef5f1c46adba3fbf35d209be9..89529e88d47fa60b078f5f05a9bfde67540fdc70 100644 (file)
@@ -54,11 +54,13 @@ struct _GtkAccelLabel
 {
   GtkLabel label;
 
-  guint             queue_id;
-  guint             accel_padding;
-  GObject   *accel_object;
-  gchar     *accel_string;
-  guint16     accel_string_width;
+  guint                 queue_id;
+  guint                 accel_padding;
+  GtkWidget     *accel_widget;
+  GClosure     *accel_closure;
+  GtkAccelGroup *accel_group;
+  gchar         *accel_string;
+  guint16        accel_string_width;
 };
 
 struct _GtkAccelLabelClass
@@ -80,20 +82,15 @@ struct _GtkAccelLabelClass
 #endif /* GTK_DISABLE_DEPRECATED */
 
 GtkType           gtk_accel_label_get_type          (void) G_GNUC_CONST;
-GtkWidget *gtk_accel_label_new              (const gchar   *string);
-GObject   *gtk_accel_label_get_accel_object  (GtkAccelLabel *accel_label);
+GtkWidgetgtk_accel_label_new              (const gchar   *string);
+GtkWidget* gtk_accel_label_get_accel_widget  (GtkAccelLabel *accel_label);
 guint     gtk_accel_label_get_accel_width   (GtkAccelLabel *accel_label);
-void      gtk_accel_label_set_accel_object  (GtkAccelLabel *accel_label,
-                                             GObject       *accel_object);
+void      gtk_accel_label_set_accel_widget  (GtkAccelLabel *accel_label,
+                                             GtkWidget     *accel_widget);
+void      gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
+                                             GClosure      *closure);
 gboolean   gtk_accel_label_refetch           (GtkAccelLabel *accel_label);
 
-#ifndef GTK_DISABLE_DEPRECATED
-#define gtk_accel_label_get_accel_widget(accel_label) \
-  GTK_WIDGET(gtk_accel_label_get_accel_object(acel_label))
-#define gtk_accel_label_set_accel_widget(accel_label, accel_widget) \
-  gtk_accel_label_set_accel_object((accel_label), G_OBJECT(accel_widget))
-#endif
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gtk/gtkaccelmap.c b/gtk/gtkaccelmap.c
new file mode 100644 (file)
index 0000000..24dca7d
--- /dev/null
@@ -0,0 +1,858 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gtkaccelmap.h"
+
+#include "gtkwindow.h"  /* in lack of GtkAcceleratable */
+
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+
+/* --- structures --- */
+typedef struct {
+  const gchar *accel_path;
+  guint        accel_key;
+  guint        accel_mods;
+  guint               std_accel_key;
+  guint               std_accel_mods;
+  guint        changed : 1;
+  GHookList   *hooks;
+} AccelEntry;
+
+
+/* --- variables --- */
+static GHashTable *accel_entry_ht = NULL;      /* accel_path -> AccelEntry */
+static GSList     *accel_filters = NULL;
+
+
+/* --- functions --- */
+static guint
+accel_entry_hash (gconstpointer key)
+{
+  const AccelEntry *entry = key;
+
+  return g_str_hash (entry->accel_path);
+}
+
+static gboolean
+accel_entry_equal (gconstpointer key1,
+                  gconstpointer key2)
+{
+  const AccelEntry *entry1 = key1;
+  const AccelEntry *entry2 = key2;
+
+  return g_str_equal (entry1->accel_path, entry2->accel_path);
+}
+
+static inline AccelEntry*
+accel_path_lookup (const gchar *accel_path)
+{
+  AccelEntry ekey;
+
+  ekey.accel_path = accel_path;
+
+  /* safety NULL check for return_if_fail()s */
+  return accel_path ? g_hash_table_lookup (accel_entry_ht, &ekey) : NULL;
+}
+
+void
+_gtk_accel_map_init (void)
+{
+  g_assert (accel_entry_ht == NULL);
+
+  accel_entry_ht = g_hash_table_new (accel_entry_hash, accel_entry_equal);
+}
+
+static gboolean
+gtk_accel_path_is_valid (const gchar *accel_path)
+{
+  gchar *p;
+
+  if (!accel_path || accel_path[0] != '<' ||
+      accel_path[1] == '<' || accel_path[1] == '>' || !accel_path[1])
+    return FALSE;
+  p = strchr (accel_path, '>');
+  if (!p || p[1] != '/')
+    return FALSE;
+  return TRUE;
+}
+
+/**
+ * gtk_accel_map_add_entry
+ * @accel_path: valid accelerator path
+ * @accel_key:  the accelerator key
+ * @accel_mods: the accelerator modifiers
+ * @returns:    the GQuark for the @accel_path (to ease local storage)
+ *
+ * Register a new accelerator with the global accelerator map.
+ * This function should only be called once per @accel_path
+ * with the canonical @accel_key and @accel_mods for this path.
+ * To change the accelerator during runtime programatically, use
+ * gtk_accel_map_change_entry().
+ * The accelerator path must consist of "<WINDOWTYPE>/Category1/Category2/.../Action",
+ * where WINDOWTYPE should be a unique application specifc identifier, that
+ * corresponds to the kind of window the accelerator is being used in, e.g. "Gimp-Image",
+ * "Abiword-Document" or "Gnumeric-Settings".
+ * The Category1/.../Action portion is most apropriately choosen by the action the
+ * accelerator triggers, i.e. for accelerators on menu items, choose the item's menu path,
+ * e.g. "File/Save As", "Image/View/Zoom" or "Edit/Select All".
+ * So a full valid accelerator path may look like:
+ * "<Gimp-Toolbox>/File/Dialogs/Tool Options...".
+ */
+GQuark
+gtk_accel_map_add_entry (const gchar *accel_path,
+                        guint        accel_key,
+                        guint        accel_mods)
+{
+  AccelEntry *entry;
+
+  g_return_val_if_fail (gtk_accel_path_is_valid (accel_path), 0);
+
+  accel_mods &= gtk_accelerator_get_default_mod_mask ();
+
+  entry = accel_path_lookup (accel_path);
+  if (entry)
+    {
+      if (!entry->std_accel_key && !entry->std_accel_mods &&
+         (accel_key || accel_mods))
+       {
+         entry->std_accel_key = accel_key;
+         entry->std_accel_mods = accel_mods;
+         if (!entry->changed)
+           gtk_accel_map_change_entry (entry->accel_path, accel_key, accel_mods, TRUE);
+       }
+    }
+  else
+    {
+      entry = g_new0 (AccelEntry, 1);
+      entry->accel_path = g_quark_to_string (g_quark_from_string (accel_path));
+      entry->std_accel_key = accel_key;
+      entry->std_accel_mods = accel_mods;
+      entry->accel_key = accel_key;
+      entry->accel_mods = accel_mods;
+      entry->changed = FALSE;
+      g_hash_table_insert (accel_entry_ht, entry, entry);
+    }
+  return g_quark_try_string (entry->accel_path);
+}
+
+typedef struct {
+  GHook          hook;
+  GtkAccelGroup *accel_group;
+} AccelHook;
+
+static void
+accel_hook_finalize (GHookList *hook_list,
+                    GHook     *hook)
+{
+  GDestroyNotify destroy = hook->destroy;
+  AccelHook *ahook = (AccelHook*) hook;
+
+  if (ahook->accel_group)
+    g_object_unref (ahook->accel_group);
+
+  if (destroy)
+    {
+      hook->destroy = NULL;
+      destroy (hook->data);
+    }
+}
+
+/**
+ * GtkAccelMapNotify
+ * @data:             notifier user data
+ * @accel_path_quark: accelerator path (as #GQuark) which has just changed
+ * @accel_key:        new accelerator key
+ * @accel_mods:       new accelerator modifiers
+ * @accel_group:      accelerator group of this notifier
+ * @old_accel_key:    former accelerator key
+ * @old_accel_mods):  former accelerator modifiers
+ *
+ * #GtkAccelMapNotify is the signature of user callbacks, installed via
+ * gtk_accel_map_add_notifier(). Once the accel path of the notifier changes,
+ * the notifier is invoked with this signature, where @accel_path_quark
+ * indicates the accel path that changed, and @data and @accel_group are
+ * the notifier's arguments as passed into gtk_accel_map_add_notifier().
+ */
+
+/**
+ * gtk_accel_map_add_notifer
+ * @accel_path:  valid accelerator path
+ * @notify_data: data argument to the notifier
+ * @notify_func: the notifier function
+ * @accel_group: accelerator group used by the notifier function
+ *
+ * Install a notifier function to be called if an accelerator
+ * map entry changes. @accel_group has to be the accel group
+ * that is being affected (gets an accelerator removed or added,
+ * when the notifier function is executed).
+ */
+void
+gtk_accel_map_add_notifer (const gchar      *accel_path,
+                          gpointer          notify_data,
+                          GtkAccelMapNotify notify_func,
+                          GtkAccelGroup    *accel_group)
+{
+  AccelEntry *entry;
+  AccelHook *ahook;
+  GHook *hook;
+
+  g_return_if_fail (gtk_accel_path_is_valid (accel_path));
+  g_return_if_fail (notify_func != NULL);
+  if (accel_group)
+    g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  entry = accel_path_lookup (accel_path);
+  if (!entry)
+    {
+      gtk_accel_map_add_entry (accel_path, 0, 0);
+      entry = accel_path_lookup (accel_path);
+    }
+  if (!entry->hooks)
+    {
+      entry->hooks = g_new (GHookList, 1);
+      g_hook_list_init (entry->hooks, sizeof (AccelHook));
+      entry->hooks->finalize_hook = accel_hook_finalize;
+    }
+  hook = g_hook_alloc (entry->hooks);
+  hook->data = notify_data;
+  hook->func = notify_func;
+  hook->destroy = NULL;
+  ahook = (AccelHook*) hook;
+  ahook->accel_group = accel_group ? g_object_ref (accel_group) : NULL;
+  g_hook_append (entry->hooks, hook);
+}
+
+/**
+ * gtk_accel_map_remove_notifer
+ * @accel_path:  valid accelerator path
+ * @notify_data: data argument to the notifier
+ * @notify_func: the notifier function
+ *
+ * Remove a notifier function, previously installed through
+ * gtk_accel_map_add_notifer().
+ */
+void
+gtk_accel_map_remove_notifer (const gchar      *accel_path,
+                             gpointer          notify_data,
+                             GtkAccelMapNotify notify_func)
+{
+  AccelEntry *entry;
+
+  g_return_if_fail (gtk_accel_path_is_valid (accel_path));
+  g_return_if_fail (notify_func != NULL);
+
+  entry = accel_path_lookup (accel_path);
+  if (entry && entry->hooks)
+    {
+      GHook *hook = g_hook_find_func_data (entry->hooks, TRUE, notify_func, notify_data);
+
+      if (hook && g_hook_destroy (entry->hooks, hook->hook_id))
+       return; /* successfully removed */
+    }
+  g_warning (G_STRLOC ": no notifier %p(%p) installed for accel path \"%s\"",
+            notify_func, notify_data, accel_path);
+}
+
+/**
+ * gtk_accel_map_lookup_entry
+ * @accel_path:  valid accelerator path
+ * @key:         accelerator key to be filled in (optional)
+ * @returns:     #GQuark for @accel_path or (0) if @accel_path is not known
+ *
+ * Lookup the accelerator entry for @accel_path and fill in @key.
+ * If the lookup revealed no results, (0) is returned, the entry's
+ * #GQuark otherwise.
+ */
+GQuark
+gtk_accel_map_lookup_entry (const gchar *accel_path,
+                           GtkAccelKey *key)
+{
+  AccelEntry *entry;
+
+  g_return_val_if_fail (gtk_accel_path_is_valid (accel_path), 0);
+
+  entry = accel_path_lookup (accel_path);
+  if (entry && key)
+    {
+      key->accel_key = entry->accel_key;
+      key->accel_mods = entry->accel_mods;
+      key->accel_flags = 0;    // FIXME: global lock?
+    }
+
+  return entry ? g_quark_try_string (entry->accel_path) : 0;
+}
+
+static void
+hash2slist_foreach (gpointer  key,
+                   gpointer  value,
+                   gpointer  user_data)
+{
+  GSList **slist_p = user_data;
+
+  *slist_p = g_slist_prepend (*slist_p, value);
+}
+
+static GSList*
+g_hash_table_slist_values (GHashTable *hash_table)
+{
+  GSList *slist = NULL;
+
+  g_return_val_if_fail (hash_table != NULL, NULL);
+
+  g_hash_table_foreach (hash_table, hash2slist_foreach, &slist);
+
+  return slist;
+}
+
+static gboolean
+internal_change_entry (const gchar    *accel_path,
+                      guint           accel_key,
+                      GdkModifierType accel_mods,
+                      gboolean        replace,
+                      gboolean        simulate)
+{
+  GSList *node, *slist, *win_list, *group_list, *replace_list = NULL;
+  GHashTable *group_hm, *win_hm;
+  gboolean change_accel, removable, can_change = TRUE, seen_accel = FALSE, hooks_may_recurse = TRUE;
+  GQuark entry_quark;
+  GHook *hook;
+  AccelEntry *entry = accel_path_lookup (accel_path);
+
+  /* not much todo if there's no entry yet */
+  if (!entry)
+    {
+      if (!simulate)
+       {
+         gtk_accel_map_add_entry (accel_path, 0, 0);
+         entry = accel_path_lookup (accel_path);
+         entry->accel_key = accel_key;
+         entry->accel_mods = accel_mods;
+         entry->changed = TRUE;
+       }
+      return TRUE;
+    }
+
+  /* if there's nothing to change, not much todo either */
+  if (entry->accel_key == accel_key && entry->accel_mods == accel_mods)
+    return FALSE;
+
+  /* nobody's interested, easy going */
+  if (!entry->hooks)
+    {
+      if (!simulate)
+       {
+         entry->accel_key = accel_key;
+         entry->accel_mods = accel_mods;
+         entry->changed = TRUE;
+       }
+      return TRUE;
+    }
+
+  /* 1) fetch all accel groups affected by this entry */
+  entry_quark = g_quark_try_string (entry->accel_path);
+  group_hm = g_hash_table_new (NULL, NULL);
+  win_hm = g_hash_table_new (NULL, NULL);
+  hook = g_hook_first_valid (entry->hooks, hooks_may_recurse);
+  while (hook)
+    {
+      AccelHook *ahook = (AccelHook*) hook;
+      
+      if (ahook->accel_group)
+       g_hash_table_insert (group_hm, ahook->accel_group, ahook->accel_group);
+      hook = g_hook_next_valid (entry->hooks, hook, hooks_may_recurse);
+    }
+
+  /* 2) collect acceleratables affected */
+  group_list = g_hash_table_slist_values (group_hm);
+  for (slist = group_list; slist; slist = slist->next)
+    {
+      GtkAccelGroup *group = slist->data;
+
+      for (node = group->acceleratables; node; node = node->next)
+       g_hash_table_insert (win_hm, node->data, node->data);
+    }
+  g_slist_free (group_list);
+
+  /* 3) include all accel groups used by acceleratables */
+  win_list = g_hash_table_slist_values (win_hm);
+  g_hash_table_destroy (win_hm);
+  for (slist = win_list; slist; slist = slist->next)
+    for (node = gtk_accel_groups_from_acceleratable (slist->data); node; node = node->next)
+      g_hash_table_insert (group_hm, node->data, node->data);
+  group_list = g_hash_table_slist_values (group_hm);
+  g_hash_table_destroy (group_hm);
+
+  /* 4) walk the acceleratables and figure whether they occupy accel_key&accel_mods */
+  for (slist = accel_key ? win_list : NULL; slist; slist = slist->next)
+    if (GTK_IS_WINDOW (slist->data))   /* bad kludge in lack of a GtkAcceleratable */
+      if (_gtk_window_query_nonaccels (slist->data, accel_key, accel_mods))
+       {
+         seen_accel = TRUE;
+         break;
+       }
+  removable = !seen_accel;
+
+  /* 5) walk all accel groups and search for locks */
+  for (slist = removable ? group_list : NULL; slist; slist = slist->next)
+    {
+      GtkAccelGroup *group = slist->data;
+      GtkAccelGroupEntry *ag_entry;
+      guint i, n;
+      
+      n = 0;
+      ag_entry = entry->accel_key ? gtk_accel_group_query (group, entry->accel_key, entry->accel_mods, &n) : NULL;
+      for (i = 0; i < n; i++)
+       if (ag_entry[i].accel_path_quark == entry_quark)
+         {
+           can_change = !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
+           if (!can_change)
+             goto break_loop_step5;
+         }
+
+      n = 0;
+      ag_entry = accel_key ? gtk_accel_group_query (group, accel_key, accel_mods, &n) : NULL;
+      for (i = 0; i < n; i++)
+       {
+         seen_accel = TRUE;
+         removable = !group->lock_count && !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
+         if (!removable)
+           goto break_loop_step5;
+         if (ag_entry[i].accel_path_quark)
+           replace_list = g_slist_prepend (replace_list, GUINT_TO_POINTER (ag_entry->accel_path_quark));
+       }
+    }
+ break_loop_step5:
+  
+  /* 6) check whether we can remove existing accelerators */
+  for (slist = removable ? replace_list : NULL; slist; slist = slist->next)
+    if (!internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, TRUE))
+      {
+       removable = FALSE;
+       break;
+      }
+
+  /* 7) check conditions and proceed if possible */
+  change_accel = can_change && (!seen_accel || (removable && replace));
+
+  if (change_accel && !simulate)
+    {
+      guint old_accel_key, old_accel_mods;
+
+      /* 8) remove existing accelerators */
+      for (slist = replace_list; slist; slist = slist->next)
+       internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, FALSE);
+
+      /* 9) install new accelerator */
+      old_accel_key = entry->accel_key;
+      old_accel_mods = entry->accel_mods;
+      entry->accel_key = accel_key;
+      entry->accel_mods = accel_mods;
+      entry->changed = TRUE;
+      hook = g_hook_first_valid (entry->hooks, hooks_may_recurse);
+      while (hook)
+       {
+         gboolean was_in_call, need_destroy = FALSE;
+         GtkAccelMapNotify hook_func = hook->func;
+         AccelHook *ahook = (AccelHook*) hook;
+         
+         was_in_call = G_HOOK_IN_CALL (hook);
+         hook->flags |= G_HOOK_FLAG_IN_CALL;
+         /* need_destroy = */ hook_func (hook->data, g_quark_try_string (entry->accel_path),
+                                         entry->accel_key, entry->accel_mods,
+                                         ahook->accel_group,
+                                         old_accel_key, old_accel_mods);
+         if (!was_in_call)
+           hook->flags &= ~G_HOOK_FLAG_IN_CALL;
+         if (need_destroy)
+           g_hook_destroy_link (entry->hooks, hook);
+         hook = g_hook_next_valid (entry->hooks, hook, hooks_may_recurse);
+       }
+    }
+  g_slist_free (replace_list);
+  g_slist_free (group_list);
+  g_slist_free (win_list);
+
+  return change_accel;
+}
+
+/**
+ * gtk_accel_map_change_entry
+ * @accel_path:  valid accelerator path
+ * @accel_key:   new accelerator key
+ * @accel_mods:  new accelerator modifiers
+ * @replace:     %TRUE if other accelerators may be deleted upon conflicts
+ * @returns:     %TRUE if the accelerator could be changed, %FALSE otherwise
+ *
+ * Change the @accel_key and @accel_mods currently associated with @accel_path.
+ * Due to conflicts with other accelerators, a change may not alwys be possible,
+ * @replace indicates whether other accelerators may be deleted to resolve such
+ * conflicts. A change will only occour if all conflicts could be resolved (which
+ * might not be the case if conflicting accelerators are locked). Succesfull
+ * changes are indicated by a %TRUE return value.
+ * Changes occouring are also indicated by invocation of notifiers attached to
+ * @accel_path (see gtk_accel_map_add_notifer() on this) and other accelerators
+ * that are being deleted.
+ */
+gboolean
+gtk_accel_map_change_entry (const gchar    *accel_path,
+                           guint           accel_key,
+                           GdkModifierType accel_mods,
+                           gboolean        replace)
+{
+  g_return_val_if_fail (gtk_accel_path_is_valid (accel_path), FALSE);
+
+  return internal_change_entry (accel_path, accel_key, accel_key ? accel_mods : 0, replace, FALSE);
+}
+
+static guint
+accel_map_parse_accel_path (GScanner *scanner)
+{
+  guint accel_key = 0, accel_mods = 0;
+  gchar *path, *accel;
+  
+  /* parse accel path */
+  g_scanner_get_next_token (scanner);
+  if (scanner->token != G_TOKEN_STRING)
+    return G_TOKEN_STRING;
+
+  /* test if the next token is an accelerator */
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token != G_TOKEN_STRING)
+    {
+      /* if not so, eat that token and error out */
+      g_scanner_get_next_token (scanner);
+      return G_TOKEN_STRING;
+    }
+
+  /* get the full accelerator specification */
+  path = g_strdup (scanner->value.v_string);
+  g_scanner_get_next_token (scanner);
+  accel = g_strdup (scanner->value.v_string);
+
+  /* ensure the entry is present */
+  gtk_accel_map_add_entry (path, 0, 0);
+
+  /* and propagate it */
+  gtk_accelerator_parse (accel, &accel_key, &accel_mods);
+  gtk_accel_map_change_entry (path, accel_key, accel_mods, TRUE);
+
+  g_free (accel);
+  g_free (path);
+
+  /* check correct statement end */
+  g_scanner_get_next_token (scanner);
+  if (scanner->token != ')')
+    return ')';
+  else
+    return G_TOKEN_NONE;
+}
+
+static void
+accel_map_parse_statement (GScanner *scanner)
+{
+  guint expected_token;
+
+  g_scanner_get_next_token (scanner);
+
+  if (scanner->token == G_TOKEN_SYMBOL)
+    {
+      guint (*parser_func) (GScanner*);
+
+      parser_func = scanner->value.v_symbol;
+
+      expected_token = parser_func (scanner);
+    }
+  else
+    expected_token = G_TOKEN_SYMBOL;
+
+  /* skip rest of statement on errrors
+   */
+  if (expected_token != G_TOKEN_NONE)
+    {
+      register guint level;
+
+      level = 1;
+      if (scanner->token == ')')
+       level--;
+      if (scanner->token == '(')
+       level++;
+
+      while (!g_scanner_eof (scanner) && level > 0)
+       {
+         g_scanner_get_next_token (scanner);
+
+         if (scanner->token == '(')
+           level++;
+         else if (scanner->token == ')')
+           level--;
+       }
+    }
+}
+
+void
+gtk_accel_map_load_scanner (GScanner *scanner)
+{
+  gboolean skip_comment_single;
+  gboolean symbol_2_token;
+  gchar *cpair_comment_single;
+  gpointer saved_symbol;
+  
+  g_return_if_fail (scanner != 0);
+
+  /* configure scanner */
+  skip_comment_single = scanner->config->skip_comment_single;
+  scanner->config->skip_comment_single = TRUE;
+  cpair_comment_single = scanner->config->cpair_comment_single;
+  scanner->config->cpair_comment_single = ";\n";
+  symbol_2_token = scanner->config->symbol_2_token;
+  scanner->config->symbol_2_token = FALSE;
+  saved_symbol = g_scanner_lookup_symbol (scanner, "gtk_accel_path");
+  g_scanner_scope_add_symbol (scanner, 0, "gtk_accel_path", accel_map_parse_accel_path);
+
+  /* outer parsing loop
+   */
+  g_scanner_peek_next_token (scanner);
+  while (scanner->next_token == '(')
+    {
+      g_scanner_get_next_token (scanner);
+
+      accel_map_parse_statement (scanner);
+
+      g_scanner_peek_next_token (scanner);
+    }
+
+  /* restore config */
+  scanner->config->skip_comment_single = skip_comment_single;
+  scanner->config->cpair_comment_single = cpair_comment_single;
+  scanner->config->symbol_2_token = symbol_2_token;
+  g_scanner_scope_remove_symbol (scanner, 0, "gtk_accel_path");
+  if (saved_symbol)
+    g_scanner_scope_add_symbol (scanner, 0, "gtk_accel_path", saved_symbol);
+}
+
+/**
+ * gtk_accel_map_load_fd
+ * @fd: valid readable file descriptor
+ *
+ * Filedescriptor variant of gtk_accel_map_load().
+ * Note that the file descriptor will not be closed by this function.
+ */
+void
+gtk_accel_map_load_fd (gint fd)
+{
+  GScanner *scanner;
+
+  g_return_if_fail (fd >= 0);
+
+  /* create and setup scanner */
+  scanner = g_scanner_new (NULL);
+  g_scanner_input_file (scanner, fd);
+
+  gtk_accel_map_load_scanner (scanner);
+
+  g_scanner_destroy (scanner);
+}
+
+/**
+ * gtk_accel_map_load
+ * @file_name: a file containing accelerator specifications
+ *
+ * Parses a file previously saved with gtk_accel_map_save() for
+ * accelerator specifications, and propagates them accordingly.
+ */
+void
+gtk_accel_map_load (const gchar *file_name)
+{
+  gint fd;
+
+  g_return_if_fail (file_name != NULL);
+
+  if (!g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
+    return;
+
+  fd = open (file_name, O_RDONLY);
+  if (fd < 0)
+    return;
+
+  gtk_accel_map_load_fd (fd);
+
+  close (fd);
+}
+
+static void
+accel_map_print (gpointer        data,
+                const gchar    *accel_path,
+                guint           accel_key,
+                guint           accel_mods,
+                gboolean        changed)
+{
+  GString *gstring = g_string_new (changed ? NULL : "; ");
+  gint err, fd = GPOINTER_TO_INT (data);
+  gchar *tmp, *name;
+
+  g_string_append (gstring, "(gtk_accel_path \"");
+
+  tmp = g_strescape (accel_path, NULL);
+  g_string_append (gstring, tmp);
+  g_free (tmp);
+
+  g_string_append (gstring, "\" \"");
+
+  name = gtk_accelerator_name (accel_key, accel_mods);
+  tmp = g_strescape (name, NULL);
+  g_free (name);
+  g_string_append (gstring, tmp);
+  g_free (tmp);
+
+  g_string_append (gstring, "\")\n");
+
+  do
+    err = write (fd, gstring->str, gstring->len);
+  while (err < 0 && errno == EINTR);
+
+  g_string_free (gstring, TRUE);
+}
+
+/**
+ * gtk_accel_map_save_fd
+ * @fd: valid writable file descriptor
+ *
+ * Filedescriptor variant of gtk_accel_map_save().
+ * Note that the file descriptor will not be closed by this function.
+ */
+void
+gtk_accel_map_save_fd (gint fd)
+{
+  GString *gstring;
+  gint err;
+
+  g_return_if_fail (fd >= 0);
+
+  gstring = g_string_new ("; ");
+  if (g_get_prgname ())
+    g_string_append (gstring, g_get_prgname ());
+  g_string_append (gstring, " GtkAccelMap rc-file         -*- scheme -*-\n");
+  g_string_append (gstring, "; this file is an automated accelerator map dump\n");
+  g_string_append (gstring, ";\n");
+
+  do
+    err = write (fd, gstring->str, gstring->len);
+  while (err < 0 && errno == EINTR);
+
+  gtk_accel_map_foreach (GINT_TO_POINTER (fd), accel_map_print);
+}
+
+/**
+ * gtk_accel_map_save
+ * @file_name: the file to contain accelerator specifications
+ *
+ * Saves current accelerator specifications (accelerator path, key
+ * and modifiers) to @file_name.
+ * The file is written in a format suitable to be read back in by
+ * gtk_accel_map_load().
+ */
+void
+gtk_accel_map_save (const gchar *file_name)
+{
+  gint fd;
+
+  g_return_if_fail (file_name != NULL);
+
+  fd = open (file_name, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+  if (fd < 0)
+    return;
+
+  gtk_accel_map_save_fd (fd);
+
+  close (fd);
+}
+
+/**
+ * gtk_accel_map_foreach
+ * @data:         data to be passed into @foreach_func
+ * @foreach_func: function to be executed for each accel map entry
+ *
+ * Loop over the entries in the accelerator map, and execute
+ * @foreach_func on each. The signature of @foreach_func is that of
+ * #GtkAccelMapForeach, the @changed parameter indicates whether
+ * this accelerator was changed during runtime (thus, would need
+ * saving during an accelerator map dump).
+ */
+void
+gtk_accel_map_foreach (gpointer           data,
+                      GtkAccelMapForeach foreach_func)
+{
+  GSList *entries, *slist, *node;
+
+  g_return_if_fail (foreach_func != NULL);
+
+  entries = g_hash_table_slist_values (accel_entry_ht);
+  for (slist = entries; slist; slist = slist->next)
+    {
+      AccelEntry *entry = slist->data;
+      gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
+
+      for (node = accel_filters; node; node = node->next)
+       if (g_pattern_match_string (node->data, entry->accel_path))
+         goto skip_accel;
+      foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
+    skip_accel:
+    }
+  g_slist_free (entries);
+}
+
+void
+gtk_accel_map_foreach_unfiltered (gpointer           data,
+                                 GtkAccelMapForeach foreach_func)
+{
+  GSList *entries, *slist;
+
+  g_return_if_fail (foreach_func != NULL);
+
+  entries = g_hash_table_slist_values (accel_entry_ht);
+  for (slist = entries; slist; slist = slist->next)
+    {
+      AccelEntry *entry = slist->data;
+      gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
+
+      foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
+    }
+  g_slist_free (entries);
+}
+
+void
+gtk_accel_map_add_filter (const gchar *filter_pattern)
+{
+  GPatternSpec *pspec;
+  GSList *slist;
+
+  g_return_if_fail (filter_pattern != NULL);
+
+  pspec = g_pattern_spec_new (filter_pattern);
+  for (slist = accel_filters; slist; slist = slist->next)
+    if (g_pattern_spec_equal (pspec, slist->data))
+      {
+       g_pattern_spec_free (pspec);
+       return;
+      }
+  accel_filters = g_slist_prepend (accel_filters, pspec);
+}
diff --git a/gtk/gtkaccelmap.h b/gtk/gtkaccelmap.h
new file mode 100644 (file)
index 0000000..99d0887
--- /dev/null
@@ -0,0 +1,81 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GTK_ACCEL_MAP_H__
+#define __GTK_ACCEL_MAP_H__
+
+
+#include <gtk/gtkaccelgroup.h>
+
+G_BEGIN_DECLS
+
+
+/* --- notifier --- */
+typedef void (*GtkAccelMapNotify)              (gpointer        data,
+                                                GQuark          accel_path_quark,
+                                                guint           accel_key,
+                                                guint           accel_mods,
+                                                GtkAccelGroup  *accel_group,
+                                                guint           old_accel_key,
+                                                guint           old_accel_mods);
+typedef void (*GtkAccelMapForeach)             (gpointer        data,
+                                                const gchar    *accel_path,
+                                                guint           accel_key,
+                                                guint           accel_mods,
+                                                gboolean        changed);
+
+
+/* --- public API --- */
+GQuark    gtk_accel_map_add_entry      (const gchar            *accel_path,
+                                        guint                   accel_key,
+                                        guint                   accel_mods);
+void      gtk_accel_map_add_notifer    (const gchar            *accel_path,
+                                        gpointer                notify_data,
+                                        GtkAccelMapNotify       notify_func,
+                                        GtkAccelGroup          *accel_group);
+void      gtk_accel_map_remove_notifer (const gchar            *accel_path,
+                                        gpointer                notify_data,
+                                        GtkAccelMapNotify       notify_func);
+GQuark     gtk_accel_map_lookup_entry  (const gchar            *accel_path,
+                                        GtkAccelKey            *key);
+gboolean   gtk_accel_map_change_entry  (const gchar            *accel_path,
+                                        guint                   accel_key,
+                                        GdkModifierType         accel_mods,
+                                        gboolean                replace);
+void      gtk_accel_map_load           (const gchar            *file_name);
+void      gtk_accel_map_save           (const gchar            *file_name);
+void      gtk_accel_map_foreach        (gpointer                data,
+                                        GtkAccelMapForeach      foreach_func);
+void      gtk_accel_map_load_fd        (gint                    fd);
+void      gtk_accel_map_load_scanner   (GScanner               *scanner);
+void      gtk_accel_map_save_fd        (gint                    fd);
+
+
+/* --- filter functions --- */
+void   gtk_accel_map_add_filter        (const gchar            *filter_pattern);
+void   gtk_accel_map_foreach_unfilterd (gpointer                data,
+                                        GtkAccelMapForeach      foreach_func);
+
+
+/* --- internal API --- */
+void           _gtk_accel_map_init             (void);
+
+
+G_END_DECLS
+
+#endif /* __GTK_ACCEL_MAP_H__ */
index 6ab691fbad3fb9f1525e1b317e83acbf8dc627ef..02fa3df2e6b92232d9ac84c7eec8a1ca99d602fe 100644 (file)
@@ -39,6 +39,7 @@
 #include       "gtk/gtkcheckmenuitem.h"
 #include       "gtk/gtkimagemenuitem.h"
 #include       "gtk/gtktearoffmenuitem.h"
+#include       "gtk/gtkaccelmap.h"
 #include       "gtk/gtkaccellabel.h"
 #include        "gdk/gdkkeysyms.h"
 #include       "gtk/gtkimage.h"
@@ -75,13 +76,6 @@ struct _GtkIFCBData
   gpointer               func_data;
   guint                          callback_action;
 };
-struct _GtkIFDumpData
-{
-  GtkPrintFunc  print_func;
-  gpointer      func_data;
-  guint                 modified_only : 1;
-  GPatternSpec *pspec;
-};
 
 
 /* --- prototypes --- */
@@ -114,47 +108,6 @@ static GQuark               quark_type_tearoff_item = 0;
 static GQuark           quark_type_separator_item = 0;
 static GQuark           quark_type_branch = 0;
 static GQuark           quark_type_last_branch = 0;
-static GScannerConfig  ifactory_scanner_config =
-{
-  (
-   " \t\n"
-   )                   /* cset_skip_characters */,
-  (
-   G_CSET_a_2_z
-   "_"
-   G_CSET_A_2_Z
-   )                   /* cset_identifier_first */,
-  (
-   G_CSET_a_2_z
-   "-+_0123456789"
-   G_CSET_A_2_Z
-   G_CSET_LATINS
-   G_CSET_LATINC
-   )                   /* cset_identifier_nth */,
-  ( ";\n" )            /* cpair_comment_single */,
-  
-  FALSE                        /* case_sensitive */,
-  
-  TRUE                 /* skip_comment_multi */,
-  TRUE                 /* skip_comment_single */,
-  FALSE                        /* scan_comment_multi */,
-  TRUE                 /* scan_identifier */,
-  FALSE                        /* scan_identifier_1char */,
-  FALSE                        /* scan_identifier_NULL */,
-  TRUE                 /* scan_symbols */,
-  TRUE                 /* scan_binary */,
-  TRUE                 /* scan_octal */,
-  TRUE                 /* scan_float */,
-  TRUE                 /* scan_hex */,
-  FALSE                        /* scan_hex_dollar */,
-  TRUE                 /* scan_string_sq */,
-  TRUE                 /* scan_string_dq */,
-  TRUE                 /* numbers_2_int */,
-  FALSE                        /* int_2_float */,
-  FALSE                        /* identifier_2_string */,
-  TRUE                 /* char_2_token */,
-  FALSE                        /* symbol_2_token */,
-};
 
 
 /* --- functions --- */
@@ -187,22 +140,16 @@ static void
 gtk_item_factory_class_init (GtkItemFactoryClass  *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-  GtkObjectClass *object_class;
+  GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
 
   gtk_item_factory_class = class;
-
-  parent_class = gtk_type_class (GTK_TYPE_OBJECT);
-
-  object_class = (GtkObjectClass*) class;
+  parent_class = g_type_class_peek_parent (class);
 
   gobject_class->finalize = gtk_item_factory_finalize;
 
   object_class->destroy = gtk_item_factory_destroy;
 
-  class->cpair_comment_single = g_strdup (";\n");
-
   class->item_ht = g_hash_table_new (g_str_hash, g_str_equal);
-  class->dummy = NULL;
   ifactory_item_chunks =
     g_mem_chunk_new ("GtkItemFactoryItem",
                     sizeof (GtkItemFactoryItem),
@@ -284,125 +231,6 @@ gtk_item_factory_callback_marshal (GtkWidget *widget,
     }
 }
 
-static void
-gtk_item_factory_propagate_accelerator (GtkItemFactoryItem *item,
-                                       GtkWidget          *exclude)
-{
-  GSList *widget_list;
-  GSList *slist;
-  
-  if (item->in_propagation)
-    return;
-  
-  item->in_propagation = TRUE;
-  
-  widget_list = NULL;
-  for (slist = item->widgets; slist; slist = slist->next)
-    {
-      GtkWidget *widget;
-      
-      widget = slist->data;
-      
-      if (widget != exclude)
-       {
-         gtk_widget_ref (widget);
-         widget_list = g_slist_prepend (widget_list, widget);
-       }
-    }
-  
-  for (slist = widget_list; slist; slist = slist->next)
-    {
-      GtkWidget *widget;
-      GtkAccelGroup *accel_group;
-      guint signal_id;
-      
-      widget = slist->data;
-      
-      accel_group = gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_accel_group);
-      
-      signal_id = gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget));
-      if (signal_id && accel_group)
-       {
-         if (item->accelerator_key)
-           gtk_widget_add_accelerator (widget,
-                                       "activate",
-                                       accel_group,
-                                       item->accelerator_key,
-                                       item->accelerator_mods,
-                                       GTK_ACCEL_VISIBLE);
-         else
-           {
-             GSList *work;
-             
-             work = gtk_accel_group_entries_from_object (G_OBJECT (widget));
-             while (work)
-               {
-                 GtkAccelEntry *ac_entry;
-                 
-                 ac_entry = work->data;
-                 work = work->next;
-                 if (ac_entry->accel_flags & GTK_ACCEL_VISIBLE &&
-                     ac_entry->accel_group == accel_group &&
-                     ac_entry->signal_id == signal_id)
-                   gtk_widget_remove_accelerator (GTK_WIDGET (widget),
-                                                  ac_entry->accel_group,
-                                                  ac_entry->accelerator_key,
-                                                  ac_entry->accelerator_mods);
-               }
-           }
-       }
-
-      gtk_widget_unref (widget);
-    }
-  
-  g_slist_free (widget_list);
-  
-  item->in_propagation = FALSE;
-}
-
-static gint
-gtk_item_factory_item_add_accelerator (GtkWidget         *widget,
-                                      guint               accel_signal_id,
-                                      GtkAccelGroup      *accel_group,
-                                      guint               accel_key,
-                                      guint               accel_mods,
-                                      GtkAccelFlags       accel_flags,
-                                      GtkItemFactoryItem *item)
-{
-  if (!item->in_propagation &&
-      g_slist_find (item->widgets, widget) &&
-      accel_signal_id == gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget)))
-    {
-      item->accelerator_key = accel_key;
-      item->accelerator_mods = accel_mods;
-      item->modified = TRUE;
-      
-      gtk_item_factory_propagate_accelerator (item, widget);
-    }
-
-  return TRUE;
-}
-
-static void
-gtk_item_factory_item_remove_accelerator (GtkWidget         *widget,
-                                         GtkAccelGroup      *accel_group,
-                                         guint               accel_key,
-                                         guint               accel_mods,
-                                         GtkItemFactoryItem *item)
-{
-  if (!item->in_propagation &&
-      g_slist_find (item->widgets, widget) &&
-      item->accelerator_key == accel_key &&
-      item->accelerator_mods == accel_mods)
-    {
-      item->accelerator_key = 0;
-      item->accelerator_mods = 0;
-      item->modified = TRUE;
-      
-      gtk_item_factory_propagate_accelerator (item, widget);
-    }
-}
-
 static void
 gtk_item_factory_item_remove_widget (GtkWidget         *widget,
                                     GtkItemFactoryItem *item)
@@ -416,8 +244,8 @@ void
 gtk_item_factory_add_foreign (GtkWidget      *accel_widget,
                              const gchar    *full_path,
                              GtkAccelGroup  *accel_group,
-                             guint           keyval,
-                             GdkModifierType modifiers)
+                             guint           accel_key,
+                             GdkModifierType accel_mods)
 {
   GtkItemFactoryClass *class;
   GtkItemFactoryItem *item;
@@ -427,7 +255,7 @@ gtk_item_factory_add_foreign (GtkWidget      *accel_widget,
 
   class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
 
-  keyval = keyval != GDK_VoidSymbol ? keyval : 0;
+  accel_key = accel_key != GDK_VoidSymbol ? accel_key : 0;
 
   item = g_hash_table_lookup (class->item_ht, full_path);
   if (!item)
@@ -435,11 +263,6 @@ gtk_item_factory_add_foreign (GtkWidget      *accel_widget,
       item = g_chunk_new (GtkItemFactoryItem, ifactory_item_chunks);
 
       item->path = g_strdup (full_path);
-      item->accelerator_key = keyval;
-      item->accelerator_mods = modifiers;
-      item->modified = FALSE;
-      item->in_propagation = FALSE;
-      item->dummy = NULL;
       item->widgets = NULL;
       
       g_hash_table_insert (class->item_ht, item->path, item);
@@ -470,29 +293,12 @@ gtk_item_factory_add_foreign (GtkWidget      *accel_widget,
    */
   if (gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (accel_widget)))
     {
-      if (item->accelerator_key && accel_group)
-       gtk_widget_add_accelerator (accel_widget,
-                                   "activate",
-                                   accel_group,
-                                   item->accelerator_key,
-                                   item->accelerator_mods,
-                                   GTK_ACCEL_VISIBLE);
-      else
-       gtk_widget_remove_accelerators (accel_widget,
-                                       "activate",
-                                       TRUE);
+      if (accel_key && accel_group)
+       {
+         gtk_accel_map_add_entry (full_path, accel_key, accel_mods);
+         _gtk_widget_set_accel_path (accel_widget, full_path, accel_group);
+       }
     }
-
-  /* keep track of accelerator changes
-   */
-  gtk_signal_connect_after (GTK_OBJECT (accel_widget),
-                           "add-accelerator",
-                           GTK_SIGNAL_FUNC (gtk_item_factory_item_add_accelerator),
-                           item);
-  gtk_signal_connect_after (GTK_OBJECT (accel_widget),
-                           "remove-accelerator",
-                           GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_accelerator),
-                           item);
 }
 
 static void
@@ -725,136 +531,6 @@ gtk_item_factory_path_from_widget (GtkWidget          *widget)
   return gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_item_path);
 }
 
-static gchar *
-item_factory_escape_path (const gchar *path)
-{
-  GString *str = g_string_new (NULL);
-
-  while (*path)
-    {
-      gchar c = *path;
-
-      switch (c)
-       {
-       case '\n':
-         g_string_append (str, "\\n");
-         break;
-       case '\r':
-         g_string_append (str, "\\r");
-         break;
-       case '"':
-       case '\\':
-         g_string_append_c (str, '\\');
-         /* Fall through */
-       default:
-         g_string_append_c (str, c);
-       }
-      
-      path++;
-    }
-
-  return g_string_free (str, FALSE);
-}
-
-static void
-gtk_item_factory_foreach (gpointer hash_key,
-                         gpointer value,
-                         gpointer user_data)
-{
-  GtkItemFactoryItem *item;
-  GtkIFDumpData *data;
-  gchar *string;
-  gchar *path;
-  gchar *name;
-  gchar comment_prefix[2] = "\000\000";
-
-  item = value;
-  data = user_data;
-
-  if (data->pspec && !g_pattern_match_string (data->pspec, item->path))
-    return;
-
-  comment_prefix[0] = gtk_item_factory_class->cpair_comment_single[0];
-
-  path = item_factory_escape_path (hash_key);
-  name = gtk_accelerator_name (item->accelerator_key, item->accelerator_mods);
-  string = g_strconcat (item->modified ? "" : comment_prefix,
-                       "(menu-path \"",
-                       path,
-                       "\" \"",
-                       name,
-                       "\")",
-                       NULL);
-  g_free (path);
-  g_free (name);
-
-  data->print_func (data->func_data, string);
-
-  g_free (string);
-}
-
-void
-gtk_item_factory_dump_items (GPatternSpec       *path_pspec,
-                            gboolean             modified_only,
-                            GtkPrintFunc         print_func,
-                            gpointer             func_data)
-{
-  GtkIFDumpData data;
-
-  g_return_if_fail (print_func != NULL);
-
-  if (!gtk_item_factory_class)
-    gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
-  data.print_func = print_func;
-  data.func_data = func_data;
-  data.modified_only = (modified_only != FALSE);
-  data.pspec = path_pspec;
-
-  g_hash_table_foreach (gtk_item_factory_class->item_ht, gtk_item_factory_foreach, &data);
-}
-
-void
-gtk_item_factory_print_func (gpointer     FILE_pointer,
-                            const gchar *string)
-{
-  FILE *f_out = FILE_pointer;
-
-  g_return_if_fail (FILE_pointer != NULL);
-  g_return_if_fail (string != NULL);
-  
-  fputs (string, f_out);
-  fputc ('\n', f_out);
-}
-
-void
-gtk_item_factory_dump_rc (const gchar  *file_name,
-                         GPatternSpec *path_pspec,
-                         gboolean      modified_only)
-{
-  FILE *f_out;
-
-  g_return_if_fail (file_name != NULL);
-
-  f_out = fopen (file_name, "w");
-  if (!f_out)
-    return;
-
-  fputs ("; ", f_out);
-  if (g_get_prgname ())
-    fputs (g_get_prgname (), f_out);
-  fputs (" GtkItemFactory rc-file         -*- scheme -*-\n", f_out);
-  fputs ("; this file is an automated menu-path dump\n", f_out);
-  fputs (";\n", f_out);
-
-  gtk_item_factory_dump_items (path_pspec,
-                              modified_only,
-                              gtk_item_factory_print_func,
-                              f_out);
-
-  fclose (f_out);
-}
-
 void
 gtk_item_factory_create_items (GtkItemFactory     *ifactory,
                               guint                n_entries,
@@ -1193,25 +869,32 @@ gtk_item_factory_create_item (GtkItemFactory          *ifactory,
       parent = gtk_item_factory_get_widget (ifactory, parent_path);
       g_return_if_fail (parent != NULL);
     }
-  g_free (parent_path);
 
   if (GTK_IS_OPTION_MENU (parent))
     {
       option_menu = GTK_OPTION_MENU (parent);
       if (!option_menu->menu)
-       gtk_option_menu_set_menu (option_menu, gtk_widget_new (GTK_TYPE_MENU, NULL));
+       {
+         GtkWidget *menu = g_object_new (GTK_TYPE_MENU, NULL);
+         gchar *p = g_strconcat (ifactory->path, parent_path, NULL);
+
+         gtk_menu_set_accel_path (GTK_MENU (menu), p);
+         g_free (p);
+         gtk_option_menu_set_menu (option_menu, menu);
+       }
       parent = option_menu->menu;
     }
+  g_free (parent_path);
                              
   g_return_if_fail (GTK_IS_CONTAINER (parent));
 
   accelerator = entry->accelerator;
   
   widget = gtk_widget_new (type,
-                          "GtkWidget::visible", TRUE,
-                          "GtkWidget::sensitive", (type_id != quark_type_separator_item &&
-                                                   type_id != quark_type_title),
-                          "GtkWidget::parent", parent,
+                          "visible", TRUE,
+                          "sensitive", (type_id != quark_type_separator_item &&
+                                        type_id != quark_type_title),
+                          "parent", parent,
                           NULL);
   if (option_menu && !option_menu->menu_item)
     gtk_option_menu_set_history (option_menu, 0);
@@ -1223,32 +906,26 @@ gtk_item_factory_create_item (GtkItemFactory          *ifactory,
   if (type_id == quark_type_image_item)
     {
       GdkPixbuf *pixbuf = NULL;
-      image = NULL;
 
+      image = NULL;
       pixbuf = gdk_pixbuf_new_from_inline (-1,
                                           entry->extra_data,
                                           FALSE,
                                           NULL);
-
       if (pixbuf)
        image = gtk_image_new_from_pixbuf (pixbuf);
-
       if (image)
        {
          gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
-
          gtk_widget_show (image);
        }
-
       if (pixbuf)
        g_object_unref (G_OBJECT (pixbuf));
     }
   if (type_id == quark_type_stock_item)
     {
       image = gtk_image_new_from_stock (entry->extra_data, GTK_ICON_SIZE_MENU);
-
       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
-
       gtk_widget_show (image);
 
       if (gtk_stock_lookup (entry->extra_data, &stock_item))
@@ -1257,8 +934,6 @@ gtk_item_factory_create_item (GtkItemFactory            *ifactory,
            accelerator = gtk_accelerator_name (stock_item.keyval, stock_item.modifier);
        }
     }
-  
-  
 
   /* install underline accelerators for this item
    */
@@ -1269,12 +944,11 @@ gtk_item_factory_create_item (GtkItemFactory          *ifactory,
       GtkWidget *label;
       
       label = gtk_widget_new (GTK_TYPE_ACCEL_LABEL,
-                             "GtkWidget::visible", TRUE,
-                             "GtkWidget::parent", widget,
-                             "GtkAccelLabel::accel_object", widget,
-                             "GtkMisc::xalign", 0.0,
+                             "visible", TRUE,
+                             "parent", widget,
+                             "accel_widget", widget,
+                             "xalign", 0.0,
                              NULL);
-      
       gtk_label_set_text_with_mnemonic (GTK_LABEL (label), name);
     }
   
@@ -1283,16 +957,19 @@ gtk_item_factory_create_item (GtkItemFactory          *ifactory,
   if (type_id == quark_type_branch ||
       type_id == quark_type_last_branch)
     {
+      gchar *p;
+
       if (entry->callback)
        g_warning ("gtk_item_factory_create_item(): Can't specify a callback on a branch: \"%s\"",
                   entry->path);
-      
       if (type_id == quark_type_last_branch)
        gtk_menu_item_set_right_justified (GTK_MENU_ITEM (widget), TRUE);
       
       parent = widget;
-      widget = gtk_widget_new (GTK_TYPE_MENU,
-                              NULL);
+      widget = gtk_widget_new (GTK_TYPE_MENU, NULL);
+      p = g_strconcat (ifactory->path, path, NULL);
+      gtk_menu_set_accel_path (GTK_MENU (widget), p);
+      g_free (p);
       
       gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), widget);
     }     
@@ -1306,10 +983,8 @@ gtk_item_factory_create_item (GtkItemFactory           *ifactory,
                             callback_type,
                             item_type_path,
                             widget);
-
   if (accelerator != entry->accelerator)
     g_free (accelerator);
-  
   g_free (path);
 }
 
@@ -1595,192 +1270,6 @@ gtk_item_factory_popup_with_data (GtkItemFactory        *ifactory,
                  mouse_button, time);
 }
 
-static guint
-gtk_item_factory_parse_menu_path (GScanner            *scanner,
-                                 GtkItemFactoryClass *class)
-{
-  GtkItemFactoryItem *item;
-  
-  g_scanner_get_next_token (scanner);
-  if (scanner->token != G_TOKEN_STRING)
-    return G_TOKEN_STRING;
-
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token != G_TOKEN_STRING)
-    {
-      g_scanner_get_next_token (scanner);
-      return G_TOKEN_STRING;
-    }
-
-  item = g_hash_table_lookup (class->item_ht, scanner->value.v_string);
-  if (!item)
-    {
-      item = g_chunk_new (GtkItemFactoryItem, ifactory_item_chunks);
-
-      item->path = g_strdup (scanner->value.v_string);
-      item->accelerator_key = 0;
-      item->accelerator_mods = 0;
-      item->modified = TRUE;
-      item->in_propagation = FALSE;
-      item->dummy = NULL;
-      item->widgets = NULL;
-
-      g_hash_table_insert (class->item_ht, item->path, item);
-    }
-  g_scanner_get_next_token (scanner);
-  
-  if (!item->in_propagation)
-    {
-      guint old_keyval;
-      guint old_mods;
-      
-      old_keyval = item->accelerator_key;
-      old_mods = item->accelerator_mods;
-      gtk_accelerator_parse (scanner->value.v_string,
-                            &item->accelerator_key,
-                            &item->accelerator_mods);
-      if (old_keyval != item->accelerator_key ||
-         old_mods != item->accelerator_mods)
-       {
-         item->modified = TRUE;
-         gtk_item_factory_propagate_accelerator (item, NULL);
-       }
-    }
-  
-  g_scanner_get_next_token (scanner);
-  if (scanner->token != ')')
-    return ')';
-  else
-    return G_TOKEN_NONE;
-}
-
-static void
-gtk_item_factory_parse_statement (GScanner            *scanner,
-                                 GtkItemFactoryClass *class)
-{
-  guint expected_token;
-  
-  g_scanner_get_next_token (scanner);
-  
-  if (scanner->token == G_TOKEN_SYMBOL)
-    {
-      guint (*parser_func) (GScanner*, GtkItemFactoryClass*);
-
-      parser_func = scanner->value.v_symbol;
-
-      /* check whether this is a GtkItemFactory symbol.
-       */
-      if (parser_func == gtk_item_factory_parse_menu_path)
-       expected_token = parser_func (scanner, class);
-      else
-       expected_token = G_TOKEN_SYMBOL;
-    }
-  else
-    expected_token = G_TOKEN_SYMBOL;
-
-  /* skip rest of statement on errrors
-   */
-  if (expected_token != G_TOKEN_NONE)
-    {
-      register guint level;
-
-      level = 1;
-      if (scanner->token == ')')
-       level--;
-      if (scanner->token == '(')
-       level++;
-      
-      while (!g_scanner_eof (scanner) && level > 0)
-       {
-         g_scanner_get_next_token (scanner);
-         
-         if (scanner->token == '(')
-           level++;
-         else if (scanner->token == ')')
-           level--;
-       }
-    }
-}
-
-void
-gtk_item_factory_parse_rc_string (const gchar   *rc_string)
-{
-  GScanner *scanner;
-
-  g_return_if_fail (rc_string != NULL);
-
-  if (!gtk_item_factory_class)
-    gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
-  ifactory_scanner_config.cpair_comment_single = gtk_item_factory_class->cpair_comment_single;
-  scanner = g_scanner_new (&ifactory_scanner_config);
-
-  g_scanner_input_text (scanner, rc_string, strlen (rc_string));
-
-  gtk_item_factory_parse_rc_scanner (scanner);
-
-  g_scanner_destroy (scanner);
-}
-
-void
-gtk_item_factory_parse_rc_scanner (GScanner *scanner)
-{
-  gpointer saved_symbol;
-
-  g_return_if_fail (scanner != NULL);
-
-  if (!gtk_item_factory_class)
-    gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
-  saved_symbol = g_scanner_lookup_symbol (scanner, "menu-path");
-  g_scanner_scope_remove_symbol (scanner, 0, "menu-path");
-  g_scanner_scope_add_symbol (scanner, 0, "menu-path", gtk_item_factory_parse_menu_path);
-
-  g_scanner_peek_next_token (scanner);
-
-  while (scanner->next_token == '(')
-    {
-      g_scanner_get_next_token (scanner);
-
-      gtk_item_factory_parse_statement (scanner, gtk_item_factory_class);
-
-      g_scanner_peek_next_token (scanner);
-    }
-
-  g_scanner_scope_remove_symbol (scanner, 0, "menu-path");
-  g_scanner_scope_add_symbol (scanner, 0, "menu-path", saved_symbol);
-}
-
-void
-gtk_item_factory_parse_rc (const gchar   *file_name)
-{
-  gint fd;
-  GScanner *scanner;
-
-  g_return_if_fail (file_name != NULL);
-
-  if (!g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
-    return;
-
-  fd = open (file_name, O_RDONLY);
-  if (fd < 0)
-    return;
-
-  if (!gtk_item_factory_class)
-    gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
-  ifactory_scanner_config.cpair_comment_single = gtk_item_factory_class->cpair_comment_single;
-  scanner = g_scanner_new (&ifactory_scanner_config);
-
-  g_scanner_input_file (scanner, fd);
-
-  gtk_item_factory_parse_rc_scanner (scanner);
-
-  g_scanner_destroy (scanner);
-
-  close (fd);
-}
-
 void
 gtk_item_factory_set_translate_func (GtkItemFactory      *ifactory,
                                     GtkTranslateFunc     func,
index 2fba37fd5883136ca391aa9def6eeb55e9feb1bd..394ed0fe26aad2915df62aedda39da19b800453d 100644 (file)
@@ -79,11 +79,7 @@ struct _GtkItemFactoryClass
 {
   GtkObjectClass        object_class;
 
-  gchar                        *cpair_comment_single;
-
   GHashTable           *item_ht;
-
-  gpointer               dummy;
 };
 
 struct _GtkItemFactoryEntry
@@ -122,12 +118,6 @@ struct _GtkItemFactoryEntry
 struct _GtkItemFactoryItem
 {
   gchar *path;
-  guint  accelerator_key;
-  guint  accelerator_mods;
-  guint         modified : 1;
-  guint  in_propagation : 1;
-  gchar *dummy;
-
   GSList *widgets;
 };
 
@@ -147,9 +137,6 @@ void                gtk_item_factory_construct (GtkItemFactory      *ifactory,
      
 /* These functions operate on GtkItemFactoryClass basis.
  */
-void           gtk_item_factory_parse_rc           (const gchar    *file_name);
-void           gtk_item_factory_parse_rc_string    (const gchar    *rc_string);
-void           gtk_item_factory_parse_rc_scanner   (GScanner       *scanner);
 void           gtk_item_factory_add_foreign        (GtkWidget      *accel_widget,
                                                     const gchar    *full_path,
                                                     GtkAccelGroup  *accel_group,
@@ -168,19 +155,6 @@ GtkWidget* gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory,
 GtkWidget*     gtk_item_factory_get_item_by_action   (GtkItemFactory *ifactory,
                                                       guint           action);
 
-/* If `path_pspec' is passed as `NULL', this function will iterate over
- * all hash entries. otherwise only those entries will be dumped for which
- * the pattern matches, e.g. "<Image>*...".
- */
-void   gtk_item_factory_dump_items     (GPatternSpec           *path_pspec,
-                                        gboolean                modified_only,
-                                        GtkPrintFunc            print_func,
-                                        gpointer                func_data);
-void   gtk_item_factory_dump_rc        (const gchar            *file_name,
-                                        GPatternSpec           *path_pspec,
-                                        gboolean                modified_only);
-void   gtk_item_factory_print_func     (gpointer                FILE_pointer,
-                                        const gchar            *string);
 void   gtk_item_factory_create_item    (GtkItemFactory         *ifactory,
                                         GtkItemFactoryEntry    *entry,
                                         gpointer                callback_data,
index 6e6c9452cc467ae4d51667cb1a7f35d0802ae45e..1279df02d99bf05b4802c2f78146bf4727ac1c76 100644 (file)
@@ -47,6 +47,7 @@
 
 #include <pango/pango-utils.h> /* For pango_split_file_list */
 
+#include "gtkaccelmap.h"
 #include "gtkdnd.h"
 #include "gtkversion.h"
 #include "gtkmain.h"
@@ -625,9 +626,9 @@ gtk_init_check (int  *argc,
   gtk_colormap = gdk_colormap_get_system ();
 
   gtk_type_init (0);
+  _gtk_accel_map_init ();  
   _gtk_rc_init ();
   
-  
   /* Register an exit function to make sure we are able to cleanup.
    */
   g_atexit (gtk_exit_func);
index e4917325580617b6236eea30becf0c8ec7520b6b..0cd270728c86991d5611546cdc125dc806281c4c 100644 (file)
@@ -24,6 +24,7 @@
 BOOLEAN:BOXED
 BOOLEAN:BOXED,BOXED
 BOOLEAN:ENUM
+BOOLEAN:OBJECT,UINT,UINT
 BOOLEAN:OBJECT,INT,INT,UINT
 BOOLEAN:OBJECT,STRING,STRING,BOXED
 BOOLEAN:OBJECT,BOXED,BOXED
@@ -78,7 +79,9 @@ VOID:POINTER,UINT
 VOID:STRING
 VOID:STRING,STRING
 VOID:STRING,INT,POINTER
+VOID:UINT,UINT
+VOID:UINT,UINT,BOXED
+VOID:UINT,STRING
 VOID:UINT,BOXED,UINT,FLAGS,FLAGS
 VOID:UINT,OBJECT,UINT,FLAGS,FLAGS
-VOID:UINT,STRING
 VOID:VOID
index e4917325580617b6236eea30becf0c8ec7520b6b..0cd270728c86991d5611546cdc125dc806281c4c 100644 (file)
@@ -24,6 +24,7 @@
 BOOLEAN:BOXED
 BOOLEAN:BOXED,BOXED
 BOOLEAN:ENUM
+BOOLEAN:OBJECT,UINT,UINT
 BOOLEAN:OBJECT,INT,INT,UINT
 BOOLEAN:OBJECT,STRING,STRING,BOXED
 BOOLEAN:OBJECT,BOXED,BOXED
@@ -78,7 +79,9 @@ VOID:POINTER,UINT
 VOID:STRING
 VOID:STRING,STRING
 VOID:STRING,INT,POINTER
+VOID:UINT,UINT
+VOID:UINT,UINT,BOXED
+VOID:UINT,STRING
 VOID:UINT,BOXED,UINT,FLAGS,FLAGS
 VOID:UINT,OBJECT,UINT,FLAGS,FLAGS
-VOID:UINT,STRING
 VOID:VOID
index 34781391ceac7936a212656a9be0283304fcd721..375b348c40c26536409c3e6db82a0367f9363637 100644 (file)
@@ -27,6 +27,7 @@
 #include <ctype.h>
 #include <string.h> /* memset */
 #include "gdk/gdkkeysyms.h"
+#include "gtkaccelmap.h"
 #include "gtkbindings.h"
 #include "gtklabel.h"
 #include "gtkmain.h"
@@ -76,6 +77,7 @@ static void     gtk_menu_get_property      (GObject     *object,
                                            GValue      *value,
                                            GParamSpec  *pspec);
 static void     gtk_menu_destroy           (GtkObject        *object);
+static void     gtk_menu_finalize          (GObject          *object);
 static void     gtk_menu_realize           (GtkWidget        *widget);
 static void     gtk_menu_unrealize         (GtkWidget        *widget);
 static void     gtk_menu_size_request      (GtkWidget        *widget,
@@ -83,6 +85,7 @@ static void     gtk_menu_size_request      (GtkWidget        *widget,
 static void     gtk_menu_size_allocate     (GtkWidget        *widget,
                                            GtkAllocation    *allocation);
 static void     gtk_menu_paint             (GtkWidget        *widget);
+static void     gtk_menu_show              (GtkWidget        *widget);
 static gboolean gtk_menu_expose            (GtkWidget        *widget,
                                            GdkEventExpose   *event);
 static gboolean gtk_menu_key_press         (GtkWidget        *widget,
@@ -161,21 +164,16 @@ gtk_menu_get_type (void)
 static void
 gtk_menu_class_init (GtkMenuClass *class)
 {
-  GObjectClass *gobject_class;
-  GtkObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-  GtkContainerClass *container_class;
-  GtkMenuShellClass *menu_shell_class;
-
+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+  GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+  GtkMenuShellClass *menu_shell_class = GTK_MENU_SHELL_CLASS (class);
   GtkBindingSet *binding_set;
   
-  gobject_class = (GObjectClass*) class;
-  object_class = (GtkObjectClass*) class;
-  widget_class = (GtkWidgetClass*) class;
-  container_class = (GtkContainerClass*) class;
-  menu_shell_class = (GtkMenuShellClass*) class;
-  parent_class = gtk_type_class (gtk_menu_shell_get_type ());
+  parent_class = g_type_class_peek_parent (class);
   
+  gobject_class->finalize = gtk_menu_finalize;
   gobject_class->set_property = gtk_menu_set_property;
   gobject_class->get_property = gtk_menu_get_property;
 
@@ -192,6 +190,7 @@ gtk_menu_class_init (GtkMenuClass *class)
   widget_class->unrealize = gtk_menu_unrealize;
   widget_class->size_request = gtk_menu_size_request;
   widget_class->size_allocate = gtk_menu_size_allocate;
+  widget_class->show = gtk_menu_show;
   widget_class->expose_event = gtk_menu_expose;
   widget_class->key_press_event = gtk_menu_key_press;
   widget_class->motion_notify_event = gtk_menu_motion_notify;
@@ -388,8 +387,6 @@ gtk_menu_destroy (GtkObject *object)
   
   gtk_menu_stop_navigating_submenu (menu);
 
-  gtk_menu_set_accel_group (menu, NULL);
-
   if (menu->old_active_menu_item)
     {
       gtk_widget_unref (menu->old_active_menu_item);
@@ -403,6 +400,12 @@ gtk_menu_destroy (GtkObject *object)
       gtk_object_ref (object);
     }
   
+  if (menu->accel_group)
+    {
+      g_object_unref (menu->accel_group);
+      menu->accel_group = NULL;
+    }
+
   if (menu->toplevel)
     gtk_widget_destroy (menu->toplevel);
   if (menu->tearoff_window)
@@ -411,6 +414,15 @@ gtk_menu_destroy (GtkObject *object)
   GTK_OBJECT_CLASS (parent_class)->destroy (object);
 }
 
+static void
+gtk_menu_finalize (GObject *object)
+{
+  GtkMenu *menu = GTK_MENU (object);
+
+  g_free (menu->accel_path);
+  
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
 
 void
 gtk_menu_attach_to_widget (GtkMenu            *menu,
@@ -828,6 +840,7 @@ gtk_menu_set_accel_group (GtkMenu   *menu,
       menu->accel_group = accel_group;
       if (menu->accel_group)
        gtk_accel_group_ref (menu->accel_group);
+      _gtk_menu_refresh_accel_paths (menu, TRUE);
     }
 }
 
@@ -839,6 +852,76 @@ gtk_menu_get_accel_group (GtkMenu *menu)
   return menu->accel_group;
 }
 
+/**
+ * gtk_menu_set_accel_path
+ * @menu:       a valid #GtkMenu
+ * @accel_path: a valid accelerator path
+ *
+ * Sets an accelerator path for this menu from which accelerator paths
+ * for its immediate children, its menu items, can be constructed.
+ * The main purpose of this function is to spare the programmer the
+ * inconvenience of having to call gtk_menu_item_set_accel_path() on
+ * each menu item that should support runtime user changable accelerators.
+ * Instead, by just calling gtk_menu_set_accel_path() on their parent,
+ * each menu item of this menu, that contains a label describing its purpose,
+ * automatically gets an accel path assigned. For example, a menu containing
+ * menu items "New" and "Exit", will, after gtk_menu_set_accel_path (menu,
+ * "<Gnumeric-Sheet>/File"); has been called, assign its items the accel paths:
+ * "<Gnumeric-Sheet>/File/New" and "<Gnumeric-Sheet>/File/Exit".
+ * Assigning accel paths to menu items then enables the user to change
+ * their accelerators at runtime. More details about accelerator paths
+ * and their default setups can be found at gtk_accel_map_add_entry().
+ */
+void
+gtk_menu_set_accel_path (GtkMenu     *menu,
+                        const gchar *accel_path)
+{
+  g_return_if_fail (GTK_IS_MENU (menu));
+  if (accel_path)
+    g_return_if_fail (accel_path[0] == '<' && strchr (accel_path, '/')); /* simplistic check */
+
+  g_free (menu->accel_path);
+  menu->accel_path = g_strdup (accel_path);
+  if (menu->accel_path)
+    _gtk_menu_refresh_accel_paths (menu, FALSE);
+}
+
+typedef struct {
+  GtkMenu *menu;
+  gboolean group_changed;
+} AccelPropagation;
+
+static void
+refresh_accel_paths_froeach (GtkWidget *widget,
+                            gpointer   data)
+{
+  AccelPropagation *prop = data;
+
+  if (GTK_IS_MENU_ITEM (widget))       /* should always be true */
+    _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
+                                      prop->menu->accel_path,
+                                      prop->menu->accel_group,
+                                      prop->group_changed);
+}
+
+void
+_gtk_menu_refresh_accel_paths (GtkMenu *menu,
+                              gboolean group_changed)
+{
+  g_return_if_fail (GTK_IS_MENU (menu));
+      
+  if (menu->accel_path && menu->accel_group)
+    {
+      AccelPropagation prop;
+
+      prop.menu = menu;
+      prop.group_changed = group_changed;
+      gtk_container_foreach (GTK_CONTAINER (menu),
+                            refresh_accel_paths_froeach,
+                            &prop);
+    }
+}
+
 void
 gtk_menu_reposition (GtkMenu *menu)
 {
@@ -1480,20 +1563,33 @@ gtk_menu_expose (GtkWidget      *widget,
   return FALSE;
 }
 
+static void
+gtk_menu_show (GtkWidget *widget)
+{
+  GtkMenu *menu = GTK_MENU (widget);
+
+  _gtk_menu_refresh_accel_paths (menu, FALSE);
+
+  GTK_WIDGET_CLASS (parent_class)->show (widget);
+}
+
 static gboolean
 gtk_menu_key_press (GtkWidget  *widget,
                    GdkEventKey *event)
 {
   GtkMenuShell *menu_shell;
   GtkMenu *menu;
+  GtkAccelGroup *accel_group;
   gboolean delete = FALSE;
   gchar *accel = NULL;
+  guint accel_key, accel_mods;
   
   g_return_val_if_fail (GTK_IS_MENU (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
       
   menu_shell = GTK_MENU_SHELL (widget);
   menu = GTK_MENU (widget);
+  accel_group = gtk_menu_get_accel_group (menu);
   
   gtk_menu_stop_navigating_submenu (menu);
 
@@ -1543,58 +1639,50 @@ gtk_menu_key_press (GtkWidget   *widget,
       break;
     }
 
+  accel_key = event->keyval;
+  accel_mods = event->state & gtk_accelerator_get_default_mod_mask ();
+
   /* Modify the accelerators */
   if (menu_shell->active_menu_item &&
-      GTK_BIN (menu_shell->active_menu_item)->child &&
-      GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu == NULL &&
-      !gtk_widget_accelerators_locked (menu_shell->active_menu_item) &&
+      GTK_BIN (menu_shell->active_menu_item)->child &&                 /* no seperators */
+      GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu == NULL && /* no submenus */
       (delete ||
        (gtk_accelerator_valid (event->keyval, event->state) &&
-       (event->state ||
-        (event->keyval >= GDK_F1 && event->keyval <= GDK_F35)))))
+       (accel_mods ||
+        (accel_key >= GDK_F1 && accel_key <= GDK_F35)))))
     {
-      GtkMenuItem *menu_item;
-      GtkAccelGroup *accel_group;
-      
-      menu_item = GTK_MENU_ITEM (menu_shell->active_menu_item);
-      
-      if (!GTK_MENU (widget)->accel_group)
-       accel_group = gtk_accel_group_get_default ();
+      GtkWidget *menu_item = menu_shell->active_menu_item;
+      gboolean replace_accels = TRUE;
+      const gchar *path;
+
+      path = _gtk_widget_get_accel_path (menu_item);
+      if (!path)
+       {
+         /* can't change accelerators on menu_items without paths
+          * (basically, those items are accelerator-locked).
+          */
+         /* g_print("item has no path, menu prefix: %s\n", menu->accel_path); */
+         gdk_beep ();
+       }
       else
-       accel_group = GTK_MENU (widget)->accel_group;
-      
-      gtk_widget_remove_accelerators (GTK_WIDGET (menu_item),
-                                     gtk_signal_name (menu_item->accelerator_signal),
-                                     TRUE);
-      
-      if (!delete &&
-         0 == gtk_widget_accelerator_signal (GTK_WIDGET (menu_item),
-                                             accel_group,
-                                             event->keyval,
-                                             event->state))
        {
-         GSList *slist;
-         
-         slist = gtk_accel_group_entries_from_object (G_OBJECT (menu_item));
-         while (slist)
+         gboolean changed;
+
+         if (delete)
            {
-             GtkAccelEntry *ac_entry;
-             
-             ac_entry = slist->data;
-             
-             if (ac_entry->signal_id == menu_item->accelerator_signal)
-               break;
-             
-             slist = slist->next;
+             accel_key = 0;
+             accel_mods = 0;
+           }
+         changed = gtk_accel_map_change_entry (path, accel_key, accel_mods, replace_accels);
+
+         if (!changed)
+           {
+             /* we failed, probably because this key is in use and
+              * locked already
+              */
+             /* g_print("failed to change\n"); */
+             gdk_beep ();
            }
-         
-         if (!slist)
-           gtk_widget_add_accelerator (GTK_WIDGET (menu_item),
-                                       gtk_signal_name (menu_item->accelerator_signal),
-                                       accel_group,
-                                       event->keyval,
-                                       event->state,
-                                       GTK_ACCEL_VISIBLE);
        }
     }
   
index 3948271d1c2f6ca98e59d20aab28121844d08b46..225c9a90b2babf553f0380689a17962dee099ff0 100644 (file)
@@ -64,6 +64,7 @@ struct _GtkMenu
   GtkWidget *old_active_menu_item;
 
   GtkAccelGroup *accel_group;
+  gchar         *accel_path;
   GtkMenuPositionFunc position_func;
   gpointer position_func_data;
 
@@ -146,7 +147,10 @@ void          gtk_menu_set_active            (GtkMenu             *menu,
 void          gtk_menu_set_accel_group   (GtkMenu             *menu,
                                           GtkAccelGroup       *accel_group);
 GtkAccelGroup* gtk_menu_get_accel_group          (GtkMenu             *menu);
-
+void           gtk_menu_set_accel_path    (GtkMenu             *menu,
+                                          const gchar         *accel_path);
+void       _gtk_menu_refresh_accel_paths (GtkMenu             *menu,
+                                          gboolean             group_changed);
 
 /* A reference count is kept for a widget when it is attached to
  * a particular widget. This is typically a menu item; it may also
index edc7f4f3f4cfebdff3748ef95a68d6418ac1cfa3..e269a790f06888bd1b7b6408f0809d7c196fd77c 100644 (file)
@@ -51,6 +51,7 @@ enum {
 static void gtk_menu_item_class_init     (GtkMenuItemClass *klass);
 static void gtk_menu_item_init           (GtkMenuItem      *menu_item);
 static void gtk_menu_item_destroy        (GtkObject        *object);
+static void gtk_menu_item_finalize       (GObject          *object);
 static void gtk_menu_item_size_request   (GtkWidget        *widget,
                                          GtkRequisition   *requisition);
 static void gtk_menu_item_size_allocate  (GtkWidget        *widget,
@@ -60,6 +61,7 @@ static void gtk_menu_item_paint          (GtkWidget        *widget,
 static gint gtk_menu_item_expose         (GtkWidget        *widget,
                                          GdkEventExpose   *event);
 
+
 static void gtk_real_menu_item_select               (GtkItem     *item);
 static void gtk_real_menu_item_deselect             (GtkItem     *item);
 static void gtk_real_menu_item_activate_item        (GtkMenuItem *item);
@@ -120,18 +122,15 @@ gtk_menu_item_get_type (void)
 static void
 gtk_menu_item_class_init (GtkMenuItemClass *klass)
 {
-  GtkObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-  GtkContainerClass *container_class;
-  GtkItemClass *item_class;
-
-  object_class = (GtkObjectClass*) klass;
-  widget_class = (GtkWidgetClass*) klass;
-  container_class = (GtkContainerClass*) klass;
-  item_class = (GtkItemClass*) klass;
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GtkItemClass *item_class = GTK_ITEM_CLASS (klass);
 
-  parent_class = gtk_type_class (gtk_item_get_type ());
+  parent_class = g_type_class_peek_parent (klass);
 
+  gobject_class->finalize = gtk_menu_item_finalize;
 
   object_class->destroy = gtk_menu_item_destroy;
 
@@ -141,7 +140,7 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
   widget_class->show_all = gtk_menu_item_show_all;
   widget_class->hide_all = gtk_menu_item_hide_all;
   widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
-
+  
   container_class->forall = gtk_menu_item_forall;
 
   item_class->select = gtk_real_menu_item_select;
@@ -194,7 +193,6 @@ static void
 gtk_menu_item_init (GtkMenuItem *menu_item)
 {
   menu_item->submenu = NULL;
-  menu_item->accelerator_signal = menu_item_signals[ACTIVATE];
   menu_item->toggle_size = 0;
   menu_item->accelerator_width = 0;
   menu_item->show_submenu_indicator = FALSE;
@@ -269,8 +267,17 @@ gtk_menu_item_destroy (GtkObject *object)
   if (menu_item->submenu)
     gtk_widget_destroy (menu_item->submenu);
 
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+  GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+gtk_menu_item_finalize (GObject *object)
+{
+  GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+
+  g_free (menu_item->accel_path);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static void
@@ -897,6 +904,107 @@ gtk_menu_item_hide_all (GtkWidget *widget)
     gtk_widget_hide_all (menu_item->submenu);
 }
 
+static void
+gtk_menu_item_accel_name_foreach (GtkWidget *widget,
+                                 gpointer data)
+{
+  const gchar **path_p = data;
+
+  if (!*path_p)
+    {
+      if (GTK_IS_LABEL (widget))
+       {
+         *path_p = gtk_label_get_text (GTK_LABEL (widget));
+         if (*path_p && (*path_p)[0] == 0)
+           *path_p = NULL;
+       }
+      else if (GTK_IS_CONTAINER (widget))
+       gtk_container_foreach (GTK_CONTAINER (widget),
+                              gtk_menu_item_accel_name_foreach,
+                              data);
+    }
+}
+
+void
+_gtk_menu_item_refresh_accel_path (GtkMenuItem   *menu_item,
+                                  const gchar   *prefix,
+                                  GtkAccelGroup *accel_group,
+                                  gboolean       group_changed)
+{
+  const gchar *path;
+  GtkWidget *widget;
+
+  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  widget = GTK_WIDGET (menu_item);
+
+  path = _gtk_widget_get_accel_path (widget);
+  if (!path)                                   /* no active accel_path yet */
+    {
+      path = menu_item->accel_path;
+      if (!path && prefix)
+       {
+         gchar *postfix = NULL;
+
+         /* try to construct one from label text */
+         gtk_container_foreach (GTK_CONTAINER (menu_item),
+                                gtk_menu_item_accel_name_foreach,
+                                &postfix);
+         menu_item->accel_path = postfix ? g_strconcat (prefix, "/", postfix, NULL) : NULL;
+         path = menu_item->accel_path;
+       }
+      if (path)
+       _gtk_widget_set_accel_path (widget, path, accel_group);
+    }
+  else if (group_changed)                      /* reinstall accelerators */
+    _gtk_widget_set_accel_path (widget, path, accel_group);
+}
+
+/**
+ * gtk_menu_item_set_accel_path
+ * @menu_item:  a valid #GtkMenuItem
+ * @accel_path: accelerator path, corresponding to this menu item's funcitonality
+ *
+ * Set the accelerator path on @menu_item, through which runtime changes of the
+ * menu item's accelerator caused by the user can be identified and saved to
+ * persistant storage (see gtk_accel_map_save() on this).
+ * To setup a default accelerator for this menu item, call
+ * gtk_accel_map_add_entry() with the same @accel_path.
+ * See also gtk_accel_map_add_entry() on the specifics of accelerator paths,
+ * and gtk_menu_set_accel_path() for a more convenient variant of this function.
+ */
+void
+gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
+                             const gchar *accel_path)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+  g_return_if_fail (accel_path && accel_path[0] == '<' && strchr (accel_path, '/'));
+
+  widget = GTK_WIDGET (menu_item);
+
+  /* store new path */
+  g_free (menu_item->accel_path);
+  menu_item->accel_path = g_strdup (accel_path);
+
+  /* forget accelerators associated with old path */
+  _gtk_widget_set_accel_path (widget, NULL, NULL);
+
+  /* install accelerators associated with new path */
+  if (widget->parent)
+    {
+      GtkMenu *menu = GTK_MENU (widget->parent);
+
+      if (menu->accel_group)
+       _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
+                                          NULL,
+                                          menu->accel_group,
+                                          FALSE);
+    }
+}
+
 static void
 gtk_menu_item_forall (GtkContainer *container,
                      gboolean      include_internals,
@@ -913,5 +1021,5 @@ gtk_menu_item_forall (GtkContainer *container,
   menu_item = GTK_MENU_ITEM (container);
 
   if (bin->child)
-    (* callback) (bin->child, callback_data);
+    callback (bin->child, callback_data);
 }
index 1f46eaa8fb2af1568367a290e1a21444d5d7f06b..2b53d95e0f08827299c9489a0f52d3460da45a07 100644 (file)
@@ -54,9 +54,9 @@ struct _GtkMenuItem
   
   GtkWidget *submenu;
   
-  guint          accelerator_signal;
   guint16 toggle_size;
   guint16 accelerator_width;
+  gchar  *accel_path;
   
   guint show_submenu_indicator : 1;
   guint submenu_placement : 1;
@@ -106,6 +106,13 @@ void       gtk_menu_item_toggle_size_allocate (GtkMenuItem         *menu_item,
 void       gtk_menu_item_set_right_justified  (GtkMenuItem         *menu_item,
                                               gboolean             right_justified);
 gboolean   gtk_menu_item_get_right_justified  (GtkMenuItem         *menu_item);
+void      gtk_menu_item_set_accel_path       (GtkMenuItem         *menu_item,
+                                              const gchar         *accel_path);
+
+void     _gtk_menu_item_refresh_accel_path   (GtkMenuItem         *menu_item,
+                                              const gchar         *prefix,
+                                              GtkAccelGroup       *accel_group,
+                                              gboolean             group_changed);
 
 #ifndef GTK_DISABLE_DEPRECATED
 #define gtk_menu_item_right_justify(menu_item) gtk_menu_item_set_right_justified ((menu_item), TRUE)
index 4ed824919977b7332c8ae638211e2f30a8e9d1a0..f9b5a08284dd483d564528eeac99387d14a8d879 100644 (file)
@@ -3540,7 +3540,6 @@ gtk_notebook_menu_item_create (GtkNotebook *notebook,
 
   gtk_widget_show (page->menu_label);
   menu_item = gtk_menu_item_new ();
-  gtk_widget_lock_accelerators (menu_item);
   gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
   gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
                         gtk_notebook_real_page_position (notebook, list));
index bd666813de36a5ea893f3bd765329bcce2e20a98..28f7ed8f1b3743b693e06a8976f25f22620345fb 100644 (file)
@@ -399,8 +399,17 @@ _gtk_settings_parse_convert (GtkRcPropertyParser parser,
       if (free_gstring)
        g_string_free (gstring, TRUE);
     }
-  else if (!G_VALUE_HOLDS (src_value, G_TYPE_GSTRING) &&
-          g_value_type_transformable (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)))
+  else if (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING))
+    {
+      if (G_VALUE_HOLDS (dest_value, G_TYPE_STRING))
+       {
+         GString *gstring = g_value_get_boxed (src_value);
+
+         g_value_set_string (dest_value, gstring ? gstring->str : NULL);
+         success = !g_param_value_validate (pspec, dest_value);
+       }
+    }
+  else if (g_value_type_transformable (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)))
     success = g_param_value_convert (pspec, src_value, dest_value, TRUE);
 
   return success;
@@ -420,7 +429,7 @@ apply_queued_setting (GtkSettings      *data,
     g_object_set_property (G_OBJECT (data), pspec->name, &tmp_value);
   else
     {
-      gchar *debug = g_strdup_value_contents (&tmp_value);
+      gchar *debug = g_strdup_value_contents (&qvalue->value);
       
       g_message ("%s: failed to retrieve property `%s' of type `%s' from rc file value \"%s\" of type `%s'",
                 qvalue->origin,
@@ -519,7 +528,7 @@ _gtk_rc_property_parser_from_type (GType type)
 void
 gtk_settings_install_property (GParamSpec  *pspec)
 {
-  GtkRcPropertyParser parser = NULL;
+  GtkRcPropertyParser parser;
 
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
@@ -549,9 +558,9 @@ free_value (gpointer data)
 }
 
 void
-gtk_settings_set_property_value  (GtkSettings            *settings,
-                                 const gchar            *prop_name,
-                                 const GtkSettingsValue *new_value)
+gtk_settings_set_property_value (GtkSettings            *settings,
+                                const gchar            *prop_name,
+                                const GtkSettingsValue *new_value)
 {
   GtkSettingsValue *qvalue;
   GParamSpec *pspec;
@@ -909,7 +918,6 @@ gtk_rc_property_parse_border (const GParamSpec *pspec,
   return success;
 }
 
-
 void
 _gtk_settings_handle_event (GdkEventSetting *event)
 {
index b24741dd8feca95fd098820eda04ca1d9add2210..10f2328ef3766783a3064fd7db67a4ebdc08760c 100644 (file)
@@ -43,7 +43,7 @@ gtk_signal_newv (const gchar         *name,
   
   g_return_val_if_fail (n_params < SIGNAL_MAX_PARAMS, 0);
   
-  closure = g_signal_type_cclosure_new (object_type, function_offset);
+  closure = function_offset ? g_signal_type_cclosure_new (object_type, function_offset) : 0;
   
   return g_signal_newv (name, object_type, signal_flags, closure, NULL, NULL, marshaller, return_val, n_params, params);
 }
index 6ee796b3941855402dd3656fc20e29e3a02c2498..646ac490781fc9fbf77af4112903d04099e172ef 100644 (file)
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <locale.h>
 #include "gtkcontainer.h"
+#include "gtkaccelmap.h"
 #include "gtkiconfactory.h"
 #include "gtkintl.h"
 #include "gtkmain.h"
@@ -69,8 +70,6 @@ enum {
   DIRECTION_CHANGED,
   GRAB_NOTIFY,
   CHILD_NOTIFY,
-  ADD_ACCELERATOR,
-  REMOVE_ACCELERATOR,
   MNEMONIC_ACTIVATE,
   GRAB_FOCUS,
   FOCUS,
@@ -114,6 +113,7 @@ enum {
   WINDOW_STATE_EVENT,
   POPUP_MENU,
   SHOW_HELP,
+  ACCEL_CLOSURES_CHANGED,
   LAST_SIGNAL
 };
 
@@ -230,6 +230,8 @@ static GParamSpecPool  *style_property_spec_pool = NULL;
 
 static GQuark          quark_property_parser = 0;
 static GQuark          quark_aux_info = 0;
+static GQuark          quark_accel_path = 0;
+static GQuark          quark_accel_closures = 0;
 static GQuark          quark_event_mask = 0;
 static GQuark          quark_extension_event_mode = 0;
 static GQuark          quark_parent_window = 0;
@@ -299,6 +301,8 @@ gtk_widget_class_init (GtkWidgetClass *klass)
 
   quark_property_parser = g_quark_from_static_string ("gtk-rc-property-parser");
   quark_aux_info = g_quark_from_static_string ("gtk-aux-info");
+  quark_accel_path = g_quark_from_static_string ("gtk-accel-path");
+  quark_accel_closures = g_quark_from_static_string ("gtk-accel-closures");
   quark_event_mask = g_quark_from_static_string ("gtk-event-mask");
   quark_extension_event_mode = g_quark_from_static_string ("gtk-extension-event-mode");
   quark_parent_window = g_quark_from_static_string ("gtk-parent-window");
@@ -341,8 +345,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   klass->direction_changed = gtk_widget_direction_changed;
   klass->grab_notify = NULL;
   klass->child_notify = NULL;
-  klass->add_accelerator = (void*) gtk_accel_group_handle_add;
-  klass->remove_accelerator = (void*) gtk_accel_group_handle_remove;
   klass->mnemonic_activate = gtk_widget_real_mnemonic_activate;
   klass->grab_focus = gtk_widget_real_grab_focus;
   klass->focus = gtk_widget_real_focus;
@@ -620,12 +622,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                   g_cclosure_marshal_VOID__PARAM,
                   G_TYPE_NONE,
                   1, G_TYPE_PARAM);
-  widget_signals[ADD_ACCELERATOR] =
-    gtk_accel_group_create_add (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST,
-                               GTK_SIGNAL_OFFSET (GtkWidgetClass, add_accelerator));
-  widget_signals[REMOVE_ACCELERATOR] =
-    gtk_accel_group_create_remove (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST,
-                                  GTK_SIGNAL_OFFSET (GtkWidgetClass, remove_accelerator));
   widget_signals[MNEMONIC_ACTIVATE] =
     g_signal_new ("mnemonic_activate",
                   GTK_CLASS_TYPE (object_class),
@@ -1020,6 +1016,13 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                    GTK_SIGNAL_OFFSET (GtkWidgetClass, show_help),
                     gtk_marshal_NONE__ENUM,
                    GTK_TYPE_NONE, 1, GTK_TYPE_WIDGET_HELP_TYPE);
+  widget_signals[ACCEL_CLOSURES_CHANGED] =
+    gtk_signal_new ("accel_closures_changed",
+                   0,
+                   GTK_CLASS_TYPE (object_class),
+                   0,
+                    gtk_marshal_NONE__NONE,
+                   GTK_TYPE_NONE, 0);
   
   binding_set = gtk_binding_set_by_class (klass);
   gtk_binding_entry_add_signal (binding_set, GDK_F10, GDK_SHIFT_MASK,
@@ -1035,7 +1038,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                                 "show_help", 1,
                                 GTK_TYPE_WIDGET_HELP_TYPE,
                                 GTK_WIDGET_HELP_TOOLTIP);
-  
   gtk_binding_entry_add_signal (binding_set, GDK_F1, GDK_SHIFT_MASK,
                                 "show_help", 1,
                                 GTK_TYPE_WIDGET_HELP_TYPE,
@@ -2497,148 +2499,305 @@ gtk_widget_real_size_allocate (GtkWidget     *widget,
      }
 }
 
+typedef struct {
+  GClosure   closure;
+  guint      signal_id;
+} AccelClosure;
+
 static void
-gtk_widget_stop_add_accelerator (GtkWidget *widget)
+closure_accel_activate (GClosure     *closure,
+                       GValue       *return_value,
+                       guint         n_param_values,
+                       const GValue *param_values,
+                       gpointer      invocation_hint,
+                       gpointer      marshal_data)
 {
-  g_return_if_fail (GTK_IS_WIDGET (widget));
+  AccelClosure *aclosure = (AccelClosure*) closure;
 
-  gtk_signal_emit_stop (GTK_OBJECT (widget), widget_signals[ADD_ACCELERATOR]);
+  if (GTK_WIDGET_IS_SENSITIVE (closure->data))
+    g_signal_emit (closure->data, aclosure->signal_id, 0);
+
+  /* we handled the accelerator */
+  g_value_set_boolean (return_value, TRUE);
 }
 
 static void
-gtk_widget_stop_remove_accelerator (GtkWidget *widget)
+closures_destroy (gpointer data)
 {
-  g_return_if_fail (GTK_IS_WIDGET (widget));
+  GSList *slist, *closures = data;
 
-  gtk_signal_emit_stop (GTK_OBJECT (widget), widget_signals[REMOVE_ACCELERATOR]);
+  for (slist = closures; slist; slist = slist->next)
+    {
+      g_closure_invalidate (slist->data);
+      g_closure_unref (slist->data);
+    }
+  g_slist_free (closures);
 }
 
-void
-gtk_widget_lock_accelerators (GtkWidget *widget)
+static GClosure*
+widget_new_accel_closure (GtkWidget *widget,
+                         guint      signal_id)
 {
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-  
-  if (!gtk_widget_accelerators_locked (widget))
+  AccelClosure *aclosure;
+  GClosure *closure = NULL;
+  GSList *slist, *closures;
+
+  closures = g_object_steal_qdata (G_OBJECT (widget), quark_accel_closures);
+  for (slist = closures; slist; slist = slist->next)
+    if (!gtk_accel_group_from_accel_closure (slist->data))
+      {
+       /* reuse this closure */
+       closure = slist->data;
+       break;
+      }
+  if (!closure)
     {
-      gtk_signal_connect (GTK_OBJECT (widget),
-                         "add_accelerator",
-                         GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
-                         NULL);
-      gtk_signal_connect (GTK_OBJECT (widget),
-                         "remove_accelerator",
-                         GTK_SIGNAL_FUNC (gtk_widget_stop_remove_accelerator),
-                         NULL);
+      closure = g_closure_new_object (sizeof (AccelClosure), G_OBJECT (widget));
+      closures = g_slist_prepend (closures, g_closure_ref (closure));
+      g_closure_sink (closure);
+      g_closure_set_marshal (closure, closure_accel_activate);
     }
+  g_object_set_qdata_full (G_OBJECT (widget), quark_accel_closures, closures, closures_destroy);
+  
+  aclosure = (AccelClosure*) closure;
+  g_assert (closure->data == widget);
+  g_assert (closure->marshal == closure_accel_activate);
+  aclosure->signal_id = signal_id;
+
+  return closure;
 }
 
+/**
+ * gtk_widget_add_accelerator
+ * @widget:       widget to install an accelerator on
+ * @accel_signal: widget signal to emit on accelerator actiavtion
+ * @accel_group:  accel group for this widget, added to its toplevel
+ * @accel_key:    GDK keyval of the accelerator
+ * @accel_mods:   modifier key combination of the accelerator
+ * @accel_flags:  flag accelerators, e.g. GTK_ACCEL_VISIBLE
+ *
+ * Install an accelerator for this @widget in @accel_group, that causes
+ * @accel_signal to be emitted if the accelerator is actiavted.
+ * The @accel_group needs to be added to the widget's toplevel via
+ * gtk_window_add_accel_group(), and the signal must be of type %G_RUN_ACTION.
+ * Accelerators added through this function are not user changable during
+ * runtime. If you want to support accelerators that can be changed by the
+ * user, use gtk_accel_map_add_entry() and gtk_menu_item_set_accel_path()
+ * instead.
+ */
 void
-gtk_widget_unlock_accelerators (GtkWidget *widget)
+gtk_widget_add_accelerator (GtkWidget     *widget,
+                           const gchar   *accel_signal,
+                           GtkAccelGroup *accel_group,
+                           guint          accel_key,
+                           guint          accel_mods,
+                           GtkAccelFlags  accel_flags)
 {
+  GClosure *closure;
+  GSignalQuery query;
+
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  
-  if (gtk_widget_accelerators_locked (widget))
+  g_return_if_fail (accel_signal != NULL);
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  g_signal_query (g_signal_lookup (accel_signal, G_OBJECT_TYPE (widget)), &query);
+  if (!query.signal_id ||
+      !(query.signal_flags & G_SIGNAL_ACTION) ||
+      query.return_type != G_TYPE_NONE ||
+      query.n_params)
     {
-      gtk_signal_disconnect_by_func (GTK_OBJECT (widget),
-                                    GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
-                                    NULL);
-      gtk_signal_disconnect_by_func (GTK_OBJECT (widget),
-                                    GTK_SIGNAL_FUNC (gtk_widget_stop_remove_accelerator),
-                                    NULL);
+      /* hmm, should be elaborate enough */
+      g_warning (G_STRLOC ": widget `%s' has no activatable signal \"%s\" without arguments",
+                G_OBJECT_TYPE_NAME (widget), accel_signal);
+      return;
     }
+
+  closure = widget_new_accel_closure (widget, query.signal_id);
+
+  /* install the accelerator. since we don't map this onto an accel_path,
+   * the accelerator will automatically be locked.
+   */
+  gtk_accel_group_connect (accel_group,
+                          accel_key,
+                          accel_mods,
+                          accel_flags | GTK_ACCEL_LOCKED,
+                          closure,
+                          0);
+
+  g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
 }
 
+/**
+ * gtk_widget_remove_accelerator
+ * @widget:       widget to install an accelerator on
+ * @accel_group:  accel group for this widget
+ * @accel_key:    GDK keyval of the accelerator
+ * @accel_mods:   modifier key combination of the accelerator
+ * @returns:      whether an accelerator was installed and could be removed
+ *
+ * Remove an accelerator from @widget, previously installed with
+ * gtk_widget_add_accelerator().
+ */
 gboolean
-gtk_widget_accelerators_locked (GtkWidget *widget)
+gtk_widget_remove_accelerator (GtkWidget     *widget,
+                              GtkAccelGroup *accel_group,
+                              guint          accel_key,
+                              guint          accel_mods)
 {
-  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  GtkAccelGroupEntry *ag_entry;
+  GSList *slist;
+  guint n, i;
   
-  return gtk_signal_handler_pending_by_func (GTK_OBJECT (widget),
-                                            widget_signals[ADD_ACCELERATOR],
-                                            TRUE,
-                                            GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
-                                            NULL) > 0;
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+  ag_entry = gtk_accel_group_query (accel_group, accel_key, accel_mods, &n);
+  for (slist = _gtk_widget_get_accel_closures (widget); slist; slist = slist->next)
+    {
+      /* paranoid sanity checking */
+      for (i = 0; i < n; i++)
+       if (slist->data == (gpointer) ag_entry[i].closure)
+         {
+           gboolean is_removed = gtk_accel_groups_disconnect_closure (slist->data);
+           g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
+           return is_removed;
+         }
+    }
+
+  g_warning (G_STRLOC ": no accelerator (%u,%u) installed in accel group (%p) for %s (%p)",
+            accel_key, accel_mods, accel_group,
+            G_OBJECT_TYPE_NAME (widget), widget);
+
+  return FALSE;
 }
 
-void
-gtk_widget_add_accelerator (GtkWidget           *widget,
-                           const gchar         *accel_signal,
-                           GtkAccelGroup       *accel_group,
-                           guint                accel_key,
-                           guint                accel_mods,
-                           GtkAccelFlags        accel_flags)
+GSList*
+_gtk_widget_get_accel_closures (GtkWidget *widget)
 {
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (accel_group != NULL);
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
-  gtk_accel_group_add (accel_group,
-                      accel_key,
-                      accel_mods,
-                      accel_flags,
-                      (GObject*) widget,
-                      accel_signal);
+  return g_object_get_qdata (G_OBJECT (widget), quark_accel_closures);
 }
 
-void
-gtk_widget_remove_accelerator (GtkWidget           *widget,
-                              GtkAccelGroup       *accel_group,
-                              guint                accel_key,
-                              guint                accel_mods)
+typedef struct {
+  GtkWidget     *widget;
+  GtkAccelGroup *accel_group;
+  const gchar   *path;
+  GClosure      *closure;
+} AccelPath;
+
+static void
+accel_path_changed (gpointer        data,
+                   GQuark          accel_path_quark,
+                   guint           accel_key,
+                   guint           accel_mods,
+                   GtkAccelGroup  *accel_group,
+                   guint           old_accel_key,
+                   guint           old_accel_mods)
+{
+  AccelPath *apath = data;
+  gboolean notify = FALSE;
+  
+  if (apath->closure)
+    {
+      /* the closure might have been removed already (due to replacements) */
+      gtk_accel_groups_disconnect_closure (apath->closure);
+      g_closure_unref (apath->closure);
+      apath->closure = NULL;
+      notify = TRUE;
+    }
+  if (accel_key)
+    {
+      apath->closure = widget_new_accel_closure (apath->widget, GTK_WIDGET_GET_CLASS (apath->widget)->activate_signal);
+      g_closure_ref (apath->closure);
+      /* need to specify path to get an unlocked accelerator */
+      gtk_accel_group_connect (apath->accel_group,
+                              accel_key,
+                              accel_mods,
+                              GTK_ACCEL_VISIBLE,
+                              apath->closure,
+                              accel_path_quark);
+      notify = TRUE;
+    }
+  if (notify)
+    g_signal_emit (apath->widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
+}
+
+static void
+destroy_accel_path (gpointer data)
 {
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (accel_group != NULL);
+  AccelPath *apath = data;
+
+  /* stop notification */
+  gtk_accel_map_remove_notifer (apath->path, apath, accel_path_changed);
 
-  gtk_accel_group_remove (accel_group,
-                         accel_key,
-                         accel_mods,
-                         (GObject*) widget);
+  /* if the closure is currently connected, get rid of that connection */
+  if (apath->closure)
+    {
+      gtk_accel_groups_disconnect_closure (apath->closure);
+      g_closure_unref (apath->closure);
+    }
+  g_object_unref (apath->accel_group);
+  g_free (apath);
 }
 
+/* accel_group: the accel group used to activate this widget
+ * accel_path:  the accel path, associating the accelerator
+ *              to activate this widget
+ * set accel path through which this widget can be actiavated.
+ */
 void
-gtk_widget_remove_accelerators (GtkWidget           *widget,
-                               const gchar         *accel_signal,
-                               gboolean             visible_only)
+_gtk_widget_set_accel_path (GtkWidget     *widget,
+                           const gchar   *accel_path,
+                           GtkAccelGroup *accel_group)
 {
-  GSList *slist;
-  guint signal_id;
-  
+  AccelPath *apath;
+  GtkAccelKey key;
+
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (accel_signal != NULL);
-  
-  signal_id = gtk_signal_lookup (accel_signal, GTK_OBJECT_TYPE (widget));
-  g_return_if_fail (signal_id != 0);
-  
-  slist = gtk_accel_group_entries_from_object (G_OBJECT (widget));
-  while (slist)
+  g_return_if_fail (GTK_WIDGET_GET_CLASS (widget)->activate_signal != 0);
+  if (accel_path)
+    g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  if (accel_path)
     {
-      GtkAccelEntry *ac_entry;
-      
-      ac_entry = slist->data;
-      slist = slist->next;
-      if (ac_entry->accel_flags & GTK_ACCEL_VISIBLE &&
-         ac_entry->signal_id == signal_id)
-       gtk_widget_remove_accelerator (GTK_WIDGET (widget),
-                                      ac_entry->accel_group,
-                                      ac_entry->accelerator_key,
-                                      ac_entry->accelerator_mods);
+      GQuark quark_path = gtk_accel_map_add_entry (accel_path, 0, 0);
+
+      if (!quark_path)
+       return;         /* pathologic anyway */
+
+      apath = g_new (AccelPath, 1);
+      apath->widget = widget;
+      apath->accel_group = g_object_ref (accel_group);
+      apath->path = g_quark_to_string (quark_path);
+      apath->closure = NULL;
+    }
+  else
+    apath = NULL;
+
+  /* also removes possible old settings */
+  g_object_set_qdata_full (G_OBJECT (widget), quark_accel_path, apath, destroy_accel_path);
+
+  if (apath)
+    {
+      /* setup accel path hooks to react to changes */
+      gtk_accel_map_add_notifer (apath->path, apath, accel_path_changed, apath->accel_group);
+
+      /* install accelerators for this path */
+      if (gtk_accel_map_lookup_entry (apath->path, &key))
+       accel_path_changed (apath, g_quark_try_string (apath->path), key.accel_key, key.accel_mods, NULL, 0, 0);
     }
 }
 
-guint
-gtk_widget_accelerator_signal (GtkWidget           *widget,
-                              GtkAccelGroup       *accel_group,
-                              guint                accel_key,
-                              guint                accel_mods)
+const gchar*
+_gtk_widget_get_accel_path (GtkWidget *widget)
 {
-  GtkAccelEntry *ac_entry;
+  AccelPath *apath;
 
-  g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
-  g_return_val_if_fail (accel_group != NULL, 0);
-
-  ac_entry = gtk_accel_group_get_entry (accel_group, accel_key, accel_mods);
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
-  if (ac_entry && ac_entry->object == (GObject*) widget)
-    return ac_entry->signal_id;
-  return 0;
+  apath = g_object_get_qdata (G_OBJECT (widget), quark_accel_path);
+  return apath ? apath->path : NULL;
 }
 
 gboolean
@@ -5361,6 +5520,10 @@ gtk_widget_real_destroy (GtkObject *object)
    */
   widget = GTK_WIDGET (object);
 
+  /* wipe accelerator closures (keep order) */
+  g_object_set_qdata (G_OBJECT (widget), quark_accel_path, NULL);
+  g_object_set_qdata (G_OBJECT (widget), quark_accel_closures, NULL);
+
   gtk_grab_remove (widget);
   gtk_selection_remove_all (widget);
   
index 3d9969a249235f1dd759cbbb90c596aeca2f0fff..ee464fa436bbe268ee2f3a3e84401448c650a1ba 100644 (file)
@@ -277,18 +277,6 @@ struct _GtkWidgetClass
   void (* child_notify)        (GtkWidget       *widget,
                                GParamSpec       *pspec);
   
-  /* accelerators */
-  void (* add_accelerator)     (GtkWidget      *widget,
-                               guint           accel_signal_id,
-                               GtkAccelGroup  *accel_group,
-                               guint           accel_key,
-                               GdkModifierType accel_mods,
-                               GtkAccelFlags   accel_flags);
-  void (* remove_accelerator)  (GtkWidget      *widget,
-                               GtkAccelGroup  *accel_group,
-                               guint           accel_key,
-                               GdkModifierType accel_mods);
-
   /* Mnemonics */
   gboolean (* mnemonic_activate) (GtkWidget    *widget,
                                  gboolean      group_cycling);
@@ -496,20 +484,15 @@ void         gtk_widget_add_accelerator     (GtkWidget           *widget,
                                           guint                accel_key,
                                           guint                accel_mods,
                                           GtkAccelFlags        accel_flags);
-void      gtk_widget_remove_accelerator  (GtkWidget           *widget,
-                                          GtkAccelGroup       *accel_group,
-                                          guint                accel_key,
-                                          guint                accel_mods);
-void      gtk_widget_remove_accelerators (GtkWidget           *widget,
-                                          const gchar         *accel_signal,
-                                          gboolean             visible_only);
-guint     gtk_widget_accelerator_signal  (GtkWidget           *widget,
+gboolean   gtk_widget_remove_accelerator  (GtkWidget           *widget,
                                           GtkAccelGroup       *accel_group,
                                           guint                accel_key,
                                           guint                accel_mods);
-void      gtk_widget_lock_accelerators   (GtkWidget           *widget);
-void      gtk_widget_unlock_accelerators (GtkWidget           *widget);
-gboolean   gtk_widget_accelerators_locked (GtkWidget          *widget);
+void         _gtk_widget_set_accel_path   (GtkWidget           *widget,
+                                          const gchar         *accel_path,
+                                          GtkAccelGroup       *accel_group);
+const gchar* _gtk_widget_get_accel_path   (GtkWidget           *widget);
+GSList*    _gtk_widget_get_accel_closures (GtkWidget          *widget);
 gboolean   gtk_widget_mnemonic_activate   (GtkWidget           *widget,
                                           gboolean             group_cycling);
 gboolean   gtk_widget_event              (GtkWidget           *widget,
index 5641caaea7c93f1ddbad98e3bf5ca53a2213d045..d5b68cb0f5d98a5b634dc20d10b821c24affe791 100644 (file)
@@ -45,6 +45,7 @@ enum {
   ACTIVATE_FOCUS,
   ACTIVATE_DEFAULT,
   MOVE_FOCUS,
+  ACCELS_CHANGED,
   LAST_SIGNAL
 };
 
@@ -220,6 +221,7 @@ static void     gtk_window_set_default_size_internal (GtkWindow    *window,
 
 static void     gtk_window_realize_icon               (GtkWindow    *window);
 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
+static void    gtk_window_notify_accels_changed      (GtkWindow    *window);
 
 static GSList      *toplevel_list = NULL;
 static GHashTable  *mnemonic_hash_table = NULL;
@@ -309,6 +311,8 @@ gtk_window_class_init (GtkWindowClass *klass)
   
   parent_class = gtk_type_class (gtk_bin_get_type ());
 
+  mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
+
   gobject_class->dispose = gtk_window_dispose;
   gobject_class->finalize = gtk_window_finalize;
 
@@ -345,6 +349,7 @@ gtk_window_class_init (GtkWindowClass *klass)
   klass->activate_default = gtk_window_real_activate_default;
   klass->activate_focus = gtk_window_real_activate_focus;
   klass->move_focus = gtk_window_move_focus;
+  klass->accels_changed = NULL;
   
   /* Construct */
   g_object_class_install_property (gobject_class,
@@ -493,10 +498,16 @@ gtk_window_class_init (GtkWindowClass *klass)
                   G_TYPE_NONE,
                   1,
                   GTK_TYPE_DIRECTION_TYPE);
-  
-  if (!mnemonic_hash_table)
-    mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
-                                           mnemonic_equal);
+
+  window_signals[ACCELS_CHANGED] =
+    g_signal_new ("accels_changed",
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_FIRST,
+                  GTK_SIGNAL_OFFSET (GtkWindowClass, accels_changed),
+                  NULL, NULL,
+                  gtk_marshal_VOID__VOID,
+                  G_TYPE_NONE,
+                  0);
 
   /*
    * Key bindings
@@ -1001,6 +1012,38 @@ gtk_window_set_policy (GtkWindow *window,
   gtk_widget_queue_resize (GTK_WIDGET (window));
 }
 
+static gboolean
+handle_accels_changed (gpointer data)
+{
+  GtkWindow *window = GTK_WINDOW (data);
+
+  if (window->accels_changed_handler)
+    {
+      gtk_idle_remove (window->accels_changed_handler);
+      window->accels_changed_handler = 0;
+    }
+
+  g_signal_emit (window, window_signals[ACCELS_CHANGED], 0);
+
+  return FALSE;
+}
+
+static void
+gtk_window_notify_accels_changed (GtkWindow *window)
+{
+  if (!window->accels_changed_handler)
+    window->accels_changed_handler = gtk_idle_add (handle_accels_changed, window);
+}
+
+/**
+ * gtk_window_add_accel_group:
+ * @window: window to attach accelerator group to
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Associate @accel_group with @window, such that calling
+ * gtk_accel_groups_activate() on @window will activate accelerators
+ * in @accel_group.
+ **/
 void
 gtk_window_add_accel_group (GtkWindow        *window,
                            GtkAccelGroup    *accel_group)
@@ -1008,9 +1051,19 @@ gtk_window_add_accel_group (GtkWindow        *window,
   g_return_if_fail (GTK_IS_WINDOW (window));
   g_return_if_fail (accel_group != NULL);
 
-  gtk_accel_group_attach (accel_group, G_OBJECT (window));
+  _gtk_accel_group_attach (accel_group, G_OBJECT (window));
+  g_signal_connect_object (accel_group, "accel_changed",
+                          G_CALLBACK (gtk_window_notify_accels_changed),
+                          window, G_CONNECT_SWAPPED);
 }
 
+/**
+ * gtk_accel_group_detach:
+ * @accel_group: a #GtkAccelGroup
+ * @object: a #GObject
+ *
+ * Reverses the effects of gtk_window_add_accel_group().
+ **/
 void
 gtk_window_remove_accel_group (GtkWindow       *window,
                               GtkAccelGroup   *accel_group)
@@ -1018,7 +1071,10 @@ gtk_window_remove_accel_group (GtkWindow       *window,
   g_return_if_fail (GTK_IS_WINDOW (window));
   g_return_if_fail (accel_group != NULL);
 
-  gtk_accel_group_detach (accel_group, G_OBJECT (window));
+  g_signal_handlers_disconnect_by_func (accel_group,
+                                       G_CALLBACK (gtk_window_notify_accels_changed),
+                                       window);
+  _gtk_accel_group_detach (accel_group, G_OBJECT (window));
 }
 
 void
@@ -1048,6 +1104,7 @@ gtk_window_add_mnemonic (GtkWindow *window,
       mnemonic->targets = g_slist_prepend (NULL, target);
       g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
     }
+  gtk_window_notify_accels_changed (window);
 }
 
 void
@@ -1073,6 +1130,7 @@ gtk_window_remove_mnemonic (GtkWindow *window,
       g_hash_table_remove (mnemonic_hash_table, mnemonic);
       g_free (mnemonic);
     }
+  gtk_window_notify_accels_changed (window);
 }
 
 gboolean
@@ -1140,6 +1198,7 @@ gtk_window_set_mnemonic_modifier (GtkWindow      *window,
   g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
 
   window->mnemonic_modifier = modifier;
+  gtk_window_notify_accels_changed (window);
 }
 
 /**
@@ -2836,7 +2895,13 @@ gtk_window_finalize (GObject *object)
                                       &window->geometry_info->widget);
       g_free (window->geometry_info);
     }
-  
+
+  if (window->accels_changed_handler)
+    {
+      gtk_idle_remove (window->accels_changed_handler);
+      window->accels_changed_handler = 0;
+    }
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -3371,6 +3436,46 @@ gtk_window_configure_event (GtkWidget         *widget,
   return TRUE;
 }
 
+/* the accel_key and accel_mods fields of the key have to be setup
+ * upon calling this function. it'll then return whether that key
+ * is at all used as accelerator, and if so will OR in the
+ * accel_flags member of the key.
+ */
+gboolean
+_gtk_window_query_nonaccels (GtkWindow      *window,
+                            guint           accel_key,
+                            GdkModifierType accel_mods)
+{
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  /* movement keys are considered locked accels */
+  if (!accel_mods)
+    {
+      static const guint bindings[] = {
+       GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
+       GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
+      };
+      guint i;
+      
+      for (i = 0; i < G_N_ELEMENTS (bindings); i++)
+       if (bindings[i] == accel_key)
+         return TRUE;
+    }
+
+  /* mnemonics are considered locked accels */
+  if (accel_mods == window->mnemonic_modifier)
+    {
+      GtkWindowMnemonic mkey;
+
+      mkey.window = window;
+      mkey.keyval = accel_key;
+      if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
 static gint
 gtk_window_key_press_event (GtkWidget   *widget,
                            GdkEventKey *event)
@@ -3404,29 +3509,6 @@ gtk_window_key_press_event (GtkWidget   *widget,
   return handled;
 }
 
-
-static void
-gtk_window_real_activate_default (GtkWindow *window)
-{
-  gtk_window_activate_default (window);
-}
-
-static void
-gtk_window_real_activate_focus (GtkWindow *window)
-{
-  gtk_window_activate_focus (window);
-}
-
-static void
-gtk_window_move_focus (GtkWindow       *window,
-                       GtkDirectionType dir)
-{
-  gtk_widget_child_focus (GTK_WIDGET (window), dir);
-  
-  if (!GTK_CONTAINER (window)->focus_child)
-    gtk_window_set_focus (window, NULL);
-}
-
 static gint
 gtk_window_key_release_event (GtkWidget   *widget,
                              GdkEventKey *event)
@@ -3452,6 +3534,28 @@ gtk_window_key_release_event (GtkWidget   *widget,
   return handled;
 }
 
+static void
+gtk_window_real_activate_default (GtkWindow *window)
+{
+  gtk_window_activate_default (window);
+}
+
+static void
+gtk_window_real_activate_focus (GtkWindow *window)
+{
+  gtk_window_activate_focus (window);
+}
+
+static void
+gtk_window_move_focus (GtkWindow       *window,
+                       GtkDirectionType dir)
+{
+  gtk_widget_child_focus (GTK_WIDGET (window), dir);
+  
+  if (!GTK_CONTAINER (window)->focus_child)
+    gtk_window_set_focus (window, NULL);
+}
+
 static gint
 gtk_window_enter_notify_event (GtkWidget        *widget,
                               GdkEventCrossing *event)
index 57a88018106969068d6fd2b6bd05d49b8248d238..8e62e60d030c0376ed44ad090ca39a8faffbec88 100644 (file)
@@ -104,6 +104,8 @@ struct _GtkWindow
   guint frame_top;
   guint frame_right;
   guint frame_bottom;
+
+  guint accels_changed_handler;
   
   GdkModifierType mnemonic_modifier;
   gpointer gtk_reserved1;      /* For future GdkScreen * */
@@ -124,6 +126,7 @@ struct _GtkWindowClass
   void     (* activate_default)        (GtkWindow       *window);
   void     (* move_focus)              (GtkWindow       *window,
                                         GtkDirectionType direction);  
+  void    (*accels_changed)           (GtkWindow       *window);
 };
 
 #define GTK_TYPE_WINDOW_GROUP             (gtk_window_group_get_type ())
@@ -320,6 +323,11 @@ void            _gtk_window_constrain_size     (GtkWindow *window,
                                                gint      *new_height);
 GtkWindowGroup *_gtk_window_get_group          (GtkWindow *window);
 
+/* --- internal (GtkAcceleratable) --- */
+gboolean       _gtk_window_query_nonaccels     (GtkWindow      *window,
+                                                guint           accel_key,
+                                                GdkModifierType accel_mods);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 2a88f45495ebe915d91cc65bea5b5e47703df65d..d0ab8b9f7b771ca90c1f9c739a245a944388e7f5 100644 (file)
@@ -32,7 +32,11 @@ BEGIN {
       printf ("#    define GTKTYPEBUILTINS_VAR extern __declspec(dllimport)\n");
       printf ("#  endif\n");
       printf ("#else\n");
-      printf ("#  define GTKTYPEBUILTINS_VAR extern\n");
+      printf ("#  ifdef GTK_COMPILATION\n");
+      printf ("#    define GTKTYPEBUILTINS_VAR\n");
+      printf ("#  else\n");
+      printf ("#    define GTKTYPEBUILTINS_VAR extern\n");
+      printf ("#  endif\n");
       printf ("#endif\n");
       printf ("\n");
     }
index 5cbdad12dfe6849efa9b8e0af7d6fedff8a69029..dd8134bd4c4c7567e65a929a233c1184548ce6a7 100644 (file)
@@ -3047,7 +3047,7 @@ create_menus (void)
                          NULL);
       
       accel_group = gtk_accel_group_new ();
-      gtk_accel_group_attach (accel_group, G_OBJECT (window));
+      gtk_window_add_accel_group (window, accel_group);
 
       gtk_window_set_title (GTK_WINDOW (window), "menus");
       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
@@ -3103,7 +3103,7 @@ create_menus (void)
                                  accel_group,
                                  GDK_F1,
                                  0,
-                                 GTK_ACCEL_VISIBLE | GTK_ACCEL_SIGNAL_VISIBLE);
+                                 GTK_ACCEL_VISIBLE);
       menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
       gtk_widget_show (menuitem);
@@ -3128,7 +3128,6 @@ create_menus (void)
                                  GDK_F3,
                                  0,
                                  GTK_ACCEL_VISIBLE);
-      gtk_widget_lock_accelerators (menuitem);
       
       optionmenu = gtk_option_menu_new ();
       gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
@@ -3287,7 +3286,7 @@ dump_accels (gpointer             callback_data,
             guint                callback_action,
             GtkWidget           *widget)
 {
-  gtk_item_factory_dump_items (NULL, FALSE, gtk_item_factory_print_func, stdout);
+  gtk_accel_map_save_fd (1 /* stdout */);
 }
     
 static GtkItemFactoryEntry menu_items[] =
@@ -3360,7 +3359,7 @@ create_item_factory (void)
                                "<main>",
                                item_factory,
                                (GtkDestroyNotify) gtk_object_unref);
-      gtk_accel_group_attach (accel_group, G_OBJECT (window));
+      gtk_window_add_accel_group (window, accel_group);
       gtk_window_set_title (GTK_WINDOW (window), "Item Factory");
       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
       gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
index 34bf05497b16cdd19d0f5245b53d6560482b01b5..4b4cc574160559c08602ef24fa711c8174bef3b2 100644 (file)
@@ -26,6 +26,9 @@ double-click_timeout = 42
 bell-duration = 39
 bell_duration = 40
 
+gtk-cursor-blink-time = 200
+# gtk-menu-bar-accel = F10
+
 style "global-style-properties"
 {
 #  xthickness = 20